From 7e342513974b10ee7fab1850056c18f58c921b3a Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 9 Nov 2025 19:14:35 +0100 Subject: [PATCH 01/24] fixes some user experience issues --- src/lang/de.json | 65 +++++++++++++------ src/module/dialog/combatAction.mjs | 37 ++++++++--- src/module/dialog/defenseAction.mjs | 35 +++++++--- src/module/setup/partials.mjs | 1 + src/module/sheets/characterSheet.mjs | 49 +++++++++++++- src/style/atoms/_typography.scss | 1 - src/style/molecules/_equipment.scss | 18 +++-- src/style/molecules/_sidebar-elements.scss | 18 +++++ src/style/organisms/_character-sheet.scss | 9 +++ .../organisms/_combat-action-dialog.scss | 3 + src/system.json | 4 +- src/templates/actor/character/main-sheet.hbs | 39 +++++------ src/templates/dialog/combat-action.hbs | 9 +-- src/templates/dialog/defense-action.hbs | 7 +- src/templates/ui/partial-cooldown.hbs | 23 +++++++ 15 files changed, 239 insertions(+), 79 deletions(-) create mode 100644 src/templates/ui/partial-cooldown.hbs diff --git a/src/lang/de.json b/src/lang/de.json index a503b8d3..2561331e 100644 --- a/src/lang/de.json +++ b/src/lang/de.json @@ -1,22 +1,49 @@ { - "TYPES": { - "Actor": { - "Character": "Held", - "Creature": "Kreatur", - "Group": "Heldengruppe", - "Merchant": "Händler" - }, - "Item": { - "ActiveEffect": "Aktiver Effekt", - "Equipment": "Ausrüstungsgegenstand", - "Skill": "Talent", - "Advantage": "Vor-/Nachteil", - "SpecialAbility": "Sonderfertigkeit", - "Spell": "Zauber", - "Liturgy": "Liturgie", - "Species": "Spezies", - "Culture": "Kultur", - "Profession": "Profession" - } + "TYPES": { + "Actor": { + "Character": "Held", + "Creature": "Kreatur", + "Group": "Heldengruppe", + "Merchant": "Händler" + }, + "Item": { + "ActiveEffect": "Aktiver Effekt", + "Equipment": "Ausrüstungsgegenstand", + "Skill": "Talent", + "Advantage": "Vor-/Nachteil", + "SpecialAbility": "Sonderfertigkeit", + "Spell": "Zauber", + "Liturgy": "Liturgie", + "Species": "Spezies", + "Culture": "Kultur", + "Profession": "Profession" } + }, + "COOLDOWN": { + "progress": "{t} weiter durchführen", + "cancel": "{t} abbrechen", + "activate": "{t} auslösen" + }, + "WEAPON": { + "attack": "Mit {weapon} angreifen", + "parry": "Mit {weapon} parrieren", + "damage": "Mit {weapon} schaden machen", + "initiative": "Initiative würfeln" + }, + "COMBAT_DIALOG": { + "notReadyReason": { + "title": "Angriff kann aus folgenden Gründen nicht ausgeführt werden:", + "noTarget": "Kein Ziel ausgewählt", + "noWeapon": "Keine Waffe ausgewählt", + "noSkill": "Kein Waffentalent ausgewählt", + "noManeuver": "Kein Manöver ausgewählt", + "impossible": "Erschwernis zu hoch für Talentwert" + } + }, + "COMBAT_DIALOG_TP": { + "windowTitle": "Schaden Würfeln", + "regularFormula": "Schadensformel:", + "bonusDamage": "Zusätzlicher Schaden:", + "buttonText": "Würfeln" + } } diff --git a/src/module/dialog/combatAction.mjs b/src/module/dialog/combatAction.mjs index 87d9c7f4..c89f0165 100644 --- a/src/module/dialog/combatAction.mjs +++ b/src/module/dialog/combatAction.mjs @@ -50,12 +50,12 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2 */ _actor = null - constructor(actor) { + constructor(actor, data) { super(); this._actor = actor this._targetId = null - this._skillId = null - this._weaponId = null + this._skillId = data.skill ? data.skill : null + this._weaponId = data.weapon ? data.weapon : null this._defenseManeuverId = null this._actionManager = new ActionManager(this._actor) CombatActionDialog._instance = this @@ -288,9 +288,9 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2 const context = await super._prepareContext(options) context.actor = this._actor - context.distanceUnit = game.scenes.current.grid.units + context.distanceUnit = game.scenes.current?.grid.units - if (this._actor.getActiveTokens()[0]?.id) { + if (context.distanceUnit && this._actor.getActiveTokens()[0]?.id) { context.tokenDistances = this.#evaluateDistances() context.weapons = this.#evaluateWeapons() @@ -307,7 +307,28 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2 // TODO get W/M of weapon NOW - context.ready = this._targetId && this._weaponId && this._skillId && this._defenseManeuverId + if (this._targetNumber >= 0 && this._targetId && this._weaponId && this._skillId && maneuver) { + context.ready = true + } else { + context.notReadyReason = `${game.i18n.format("COMBAT_DIALOG.notReadyReason.title")}" + context.ready = false + } return context } else { ui.notifications.error(`Feature funktioniert nur wenn der Akteur ein Token auf der aktuellen Szene hat`); @@ -335,12 +356,10 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2 target.textContent = `(${result})` targetDescription.textContent = this._modDescription - if (result <= 0) { - context.ready = false + if (result <= 0 || !context.ready) { this.element.querySelector(".actions button").classList.remove("ready") this.element.querySelector(".actions button").setAttribute("disabled", true) } else { - context.ready = true this.element.querySelector(".actions button").classList.add("ready") this.element.querySelector(".actions button").removeAttribute("disabled") } diff --git a/src/module/dialog/defenseAction.mjs b/src/module/dialog/defenseAction.mjs index 6d4db78e..5e136d90 100644 --- a/src/module/dialog/defenseAction.mjs +++ b/src/module/dialog/defenseAction.mjs @@ -49,16 +49,16 @@ export class DefenseActionDialog extends HandlebarsApplicationMixin(ApplicationV */ _actor = null - constructor(actor, attackData) { + constructor(actor, data, attackData) { super(); - this._attackData = attackData ?? { + /*this._attackData = attackData ?? { modToDefense: 0, attacker: null, weapon: null, // is important to note as weapons like Chain Weapons or Flails can ignore Shields - } + }*/ this._actor = actor - this._skillId = null - this._weaponId = null + this._skillId = data.skill ? data.skill : null + this._weaponId = data.weapon ? data.weapon : null this._defenseManeuverId = null this._actionManager = new ActionManager(this._actor) //if (this._actor) { @@ -254,7 +254,26 @@ export class DefenseActionDialog extends HandlebarsApplicationMixin(ApplicationV // TODO get W/M of weapon NOW - context.ready = this._targetId && this._weaponId && this._skillId && this._defenseManeuverId + if (this._weaponId && this._skillId && this._defenseManeuverId) { + context.ready = true + } else { + context.notReadyReason = `${game.i18n.format("COMBAT_DIALOG.notReadyReason.title")}" + context.ready = false + } + return context } else { ui.notifications.error(`Feature funktioniert nur wenn der Akteur ein Token auf der aktuellen Szene hat`); @@ -282,12 +301,10 @@ export class DefenseActionDialog extends HandlebarsApplicationMixin(ApplicationV target.textContent = `(${result})` targetDescription.textContent = this._modDescription - if (result <= 0) { - context.ready = false + if (result <= 0 || !context.ready) { this.element.querySelector(".actions button").classList.remove("ready") this.element.querySelector(".actions button").setAttribute("disabled", true) } else { - context.ready = true this.element.querySelector(".actions button").classList.add("ready") this.element.querySelector(".actions button").removeAttribute("disabled") } diff --git a/src/module/setup/partials.mjs b/src/module/setup/partials.mjs index 9ff711c4..cf2de449 100644 --- a/src/module/setup/partials.mjs +++ b/src/module/setup/partials.mjs @@ -4,6 +4,7 @@ function loadPartials(hbs) { hbs.loadTemplates([ // ui partials. 'systems/DSA_4-1/templates/ui/partial-rollable-button.hbs', + 'systems/DSA_4-1/templates/ui/partial-cooldown.hbs', 'systems/DSA_4-1/templates/ui/partial-rollable-weaponskill-button.hbs', 'systems/DSA_4-1/templates/ui/partial-rollable-language-button.hbs', 'systems/DSA_4-1/templates/ui/partial-attribute-button.hbs', diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index 5508fab8..b59c2cfb 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -50,6 +50,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { activateCooldown: CharacterSheet.#activateCooldown, rest: CharacterSheet.#startResting, removeEffect: CharacterSheet.#removeEffect, + rollDamage: CharacterSheet.#rollDamage, } } @@ -202,12 +203,14 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { } static #openCombatAction(event, target) { + let {weapon, skill} = target.dataset + switch (target.dataset.mode) { case "attack": - new CombatActionDialog(this.document).render(true) + new CombatActionDialog(this.document, {weapon, skill}).render(true) break case "defense": - new DefenseActionDialog(this.document).render(true) + new DefenseActionDialog(this.document, {weapon, skill}).render(true) break } } @@ -261,6 +264,39 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { await this.document.update(formData.object) } + static async #rollDamage(event, target) { + let {weapon, isRanged} = target.dataset + isRanged = isRanged == "true" + weapon = this.document.items.get(weapon) + if (weapon) { + const damageFormula = isRanged ? weapon.system.rangedAttackDamage : weapon.system.meleeAttackDamage + const calculation = await foundry.applications.api.DialogV2.prompt({ + window: {title: game.i18n.format("COMBAT_DIALOG_TP.windowTitle")}, + content: `
`, + ok: { + label: game.i18n.format("COMBAT_DIALOG_TP.buttonText"), + callback: (event, button, dialog) => { + return { + formula: button.form.elements.formula.value, + bonusDamage: button.form.elements.bonusDamage.value + } + } + } + }); + + const sanitisedFormula = calculation.formula.replace(/wW/g, "d") + const suffix = calculation.bonusDamage >= 0 ? "+" + calculation.bonusDamage : calculation.bonusDamage + + let r = new Roll(sanitisedFormula + suffix, this.document.getRollData()); + const label = `Schadenswurf` + await r.toMessage({ + speaker: ChatMessage.getSpeaker({actor: this.document}), + flavor: label, + rollMode: game.settings.get('core', 'rollMode'), + }) + } + } + _getTabsConfig(group) { const tabs = foundry.utils.deepClone(super._getTabsConfig(group)) @@ -363,7 +399,10 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { fkitems.forEach(skill => { context.attacks.push({ name: skill.name, + id: fernkampf._id, + skillId: skill._id, using: fernkampf.name, + isRanged: true, at: `${this.document.system.fk.aktuell + skill.system.at}`, tp: `${fernkampf.system.rangedAttackDamage}`, ini: `${context.inidice}w6 + ${context.inivalue + fernkampf.system.iniModifier ?? 0}`, @@ -382,7 +421,10 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { const obj = skill context.attacks.push({ name: obj.name, + id: links._id, + skillId: skill._id, using: links.name, + isRanged: false, at: `${this.document.system.at.links.aktuell + obj.system.at + links.system.attackModifier}`, pa: `${this.document.system.pa.links.aktuell + obj.system.pa + links.system.parryModifier}`, tp: `${links.system.meleeAttackDamage}`, @@ -402,7 +444,10 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { const obj = skill context.attacks.push({ name: obj.name, + id: rechts._id, + skillId: skill._id, using: rechts.name, + isRanged: false, at: `${this.document.system.at.rechts.aktuell + obj.system.at + rechts.system.attackModifier}`, pa: `${this.document.system.pa.rechts.aktuell + obj.system.pa + rechts.system.parryModifier}`, tp: `${rechts.system.meleeAttackDamage}`, diff --git a/src/style/atoms/_typography.scss b/src/style/atoms/_typography.scss index 0827abfe..a56c325e 100644 --- a/src/style/atoms/_typography.scss +++ b/src/style/atoms/_typography.scss @@ -24,7 +24,6 @@ } input, - .rkp .pill, .cooldown > span, .attribute.rollable > .name, .attribute.rollable > .wert { diff --git a/src/style/molecules/_equipment.scss b/src/style/molecules/_equipment.scss index 8b541f92..86c606e2 100644 --- a/src/style/molecules/_equipment.scss +++ b/src/style/molecules/_equipment.scss @@ -9,14 +9,12 @@ padding: 2px 0 0 2px; margin: 4px 0 0 4px; gap: 8px; - @if darkmode { - background: rgba(0, 0, 0, 0.3); - } @else { - background: assets.$tab-pane-background; - } + background: assets.$tab-pane-background; .icon { - width: 32px; + object-fit: cover; + max-width: 32px; + max-height: 32px; padding: 0; } @@ -55,4 +53,12 @@ padding: 0 4px 4px 0; z-index: 2; } + + &.worn { + + .name { + font-weight: bold; + } + + } } \ No newline at end of file diff --git a/src/style/molecules/_sidebar-elements.scss b/src/style/molecules/_sidebar-elements.scss index 2ec297a8..7a696c23 100644 --- a/src/style/molecules/_sidebar-elements.scss +++ b/src/style/molecules/_sidebar-elements.scss @@ -133,10 +133,28 @@ .ini { grid-area: ini; + cursor: pointer; + + label { + cursor: pointer; + } + + &:hover { + text-shadow: 0 0 2px rgba(255, 0, 0, 1); + } } .tp { grid-area: tp; + cursor: pointer; + + label { + cursor: pointer; + } + + &:hover { + text-shadow: 0 0 2px rgba(255, 0, 0, 1); + } } } diff --git a/src/style/organisms/_character-sheet.scss b/src/style/organisms/_character-sheet.scss index 5b452e73..a653ed6f 100644 --- a/src/style/organisms/_character-sheet.scss +++ b/src/style/organisms/_character-sheet.scss @@ -36,6 +36,14 @@ font-size: large; } + .rkp { + + .pill { + cursor: pointer; + } + + } + } div.head-data { @@ -50,6 +58,7 @@ .profile-img { width: $sidebar-width - 16px; } + } nav.sheet-tabs.tabs { diff --git a/src/style/organisms/_combat-action-dialog.scss b/src/style/organisms/_combat-action-dialog.scss index 274d1032..e5359f2b 100644 --- a/src/style/organisms/_combat-action-dialog.scss +++ b/src/style/organisms/_combat-action-dialog.scss @@ -45,6 +45,8 @@ li { + cursor: pointer; + height: 32px; display: grid; line-height: 32px; @@ -63,6 +65,7 @@ } &.name-only { + padding-left: 40px; display: block; } } diff --git a/src/system.json b/src/system.json index 94324e87..be6b6c09 100644 --- a/src/system.json +++ b/src/system.json @@ -2,7 +2,7 @@ "id": "DSA_4-1", "title": "Das Schwarze Auge 4.1", "description": "Noch ein Spielsystem für Das Schwarze Auge 4.1", - "version": "0.5.1-rc1", + "version": "0.0.1", "compatibility": { "minimum": 12, "verified": 13 @@ -349,5 +349,5 @@ "primaryTokenAttribute": "lep.aktuell", "url": "https://git.macniel.online/macniel/foundry-dsa41-game", "manifest": "https://git.macniel.online/macniel/foundry-dsa41-game/raw/branch/main/src/system.json", - "download": "https://git.macniel.online/macniel/foundry-dsa41-game/releases/download/0.5.1-rc1/release.zip" + "download": "https://git.macniel.online/macniel/foundry-dsa41-game/releases/download/0.0.1/release.zip" } diff --git a/src/templates/actor/character/main-sheet.hbs b/src/templates/actor/character/main-sheet.hbs index e4420fc3..f4198f96 100644 --- a/src/templates/actor/character/main-sheet.hbs +++ b/src/templates/actor/character/main-sheet.hbs @@ -62,25 +62,34 @@

{{this.using}} ({{this.name}})

{{#if this.at}} - {{#each circumstances}} -
+
-

Inventar

- - +
+

Inventar

+
+ + +
+
{{> "systems/DSA_4-1/templates/ui/partial-equipment-button.hbs" equipments}}
diff --git a/src/templates/dialog/item-browser-dialog.hbs b/src/templates/dialog/item-browser-dialog.hbs index d09860f6..9dd575b3 100644 --- a/src/templates/dialog/item-browser-dialog.hbs +++ b/src/templates/dialog/item-browser-dialog.hbs @@ -1,23 +1,44 @@
+ -- 2.43.0 From cfc5bc15b15aeb0cd5ffd06f65b14be5830ea04c Mon Sep 17 00:00:00 2001 From: macniel Date: Wed, 12 Nov 2025 19:09:07 +0100 Subject: [PATCH 06/24] fixes rounding issue --- src/module/handlebar-helpers/currency.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module/handlebar-helpers/currency.mjs b/src/module/handlebar-helpers/currency.mjs index 3f83b42c..74304326 100644 --- a/src/module/handlebar-helpers/currency.mjs +++ b/src/module/handlebar-helpers/currency.mjs @@ -4,7 +4,7 @@ function currency(st) { // internally the price is always given in Silver // so we need to inflate the value of price by 100 to be able to divide beginning from Heller - const baseValue = st * 100 + const baseValue = Math.round(st * 100) // then we can regex over it -- 2.43.0 From 811806a68b097bd7d7d5cec82d093967021c1748 Mon Sep 17 00:00:00 2001 From: macniel Date: Wed, 12 Nov 2025 20:13:21 +0100 Subject: [PATCH 07/24] makes talents more subtle also adds tooltips to rollable on the skill sheet. --- src/style/atoms/_colours.scss | 14 +++---- src/style/molecules/_attribute-die.scss | 7 ++-- src/style/molecules/_rollable.scss | 24 ++++------- .../organisms/character-tabs/_skills.scss | 7 ++++ src/templates/actor/character/tab-skills.hbs | 42 ++++++++++++------- src/templates/ui/partial-rollable-button.hbs | 8 +--- .../ui/partial-rollable-language-button.hbs | 9 ++-- .../partial-rollable-weaponskill-button.hbs | 9 ++-- 8 files changed, 64 insertions(+), 56 deletions(-) diff --git a/src/style/atoms/_colours.scss b/src/style/atoms/_colours.scss index e495c79a..950f42d7 100644 --- a/src/style/atoms/_colours.scss +++ b/src/style/atoms/_colours.scss @@ -9,17 +9,17 @@ $talent-text-color: #000; $kampftalent-color: #cc0000; $kampftalent-text-color: #FFF; -$talent-body-color: #16bd6c; +$talent-body-color: #45d18c; $talent-body-text-color: #000; -$talent-nature-color: #46800d; +$talent-nature-color: #7cb544; $talent-nature-text-color: #000; -$talent-social-color: #ae9809; +$talent-social-color: #c8588a; $talent-social-text-color: #000; -$talent-knowledge-color: #d319ba; +$talent-knowledge-color: #2ba9c5; $talent-knowledge-text-color: #000; -$talent-language-color: #573bbc; -$talent-language-text-color: #fff; -$talent-crafting-color: #ae6813; +$talent-language-color: #957fe8; +$talent-language-text-color: #000; +$talent-crafting-color: #cd9551; $talent-crafting-text-color: #000; diff --git a/src/style/molecules/_attribute-die.scss b/src/style/molecules/_attribute-die.scss index c3126fcf..484520a5 100644 --- a/src/style/molecules/_attribute-die.scss +++ b/src/style/molecules/_attribute-die.scss @@ -31,11 +31,12 @@ position: absolute; left: -1px; width: 48px; - top: -1px; - font-size: smaller; + top: 2px; + font-size: large; line-height: 48px; vertical-align: middle; text-align: center; + @if $darkmode { color: colours.$attribute-die-label-color-darkmode; } @else { @@ -62,7 +63,7 @@ &.colorfulDice { - &.Mut { + .Mut { .die svg path { fill: colours.$attribute-die-co-color; diff --git a/src/style/molecules/_rollable.scss b/src/style/molecules/_rollable.scss index a1c7cb5b..642d23bd 100644 --- a/src/style/molecules/_rollable.scss +++ b/src/style/molecules/_rollable.scss @@ -52,7 +52,7 @@ $rollable_colours_font: ( .value { position: absolute; left: 0; - top: 0; + top: 1px; width: 32px; line-height: 30px; vertical-align: middle; @@ -126,9 +126,9 @@ $rollable_colours_font: ( // interactivity .block.rollable { - &:hover { + .die:hover { - .die svg { + svg { filter: drop-shadow(0px 0px 10px rgb(255 0 0)); } @@ -138,16 +138,9 @@ $rollable_colours_font: ( &:active { .die { - width: 28px; - height: 28px; - left: 2px; - top: 2px; + scale: 0.8; .value { - width: 28px; - height: 28px; - left: -1px; - top: -2px; img { position: absolute; @@ -168,7 +161,6 @@ $rollable_colours_font: ( .#{$name}.rollable { .die { - stroke-width: 0.5; svg { @@ -176,8 +168,7 @@ $rollable_colours_font: ( path { fill: $color; - stroke: colour.$rollable-die-border-color; - stroke-width: 5px; + } } @@ -189,7 +180,10 @@ $rollable_colours_font: ( } .container { - background-image: linear-gradient(to right, rgba($color, numbers.$start_gradient), rgba($color, numbers.$end_gradient)); + // background-image: linear-gradient(to right, rgba($color, numbers.$start_gradient), rgba($color, numbers.$end_gradient)); + background: rgba(0, 0, 0, 0.05); + border: 1px solid #ccc; + box-shadow: 1px 1px 1px #ccc; border-top-right-radius: 8px; border-bottom-right-radius: 8px; } diff --git a/src/style/organisms/character-tabs/_skills.scss b/src/style/organisms/character-tabs/_skills.scss index 3a2a7e4f..bbb542d0 100644 --- a/src/style/organisms/character-tabs/_skills.scss +++ b/src/style/organisms/character-tabs/_skills.scss @@ -17,6 +17,13 @@ gap: unset; padding: unset; + fieldset { + margin-top: 0; + margin-bottom: 0; + padding-top: 0; + padding-bottom: 0; + } + } ul { diff --git a/src/templates/actor/character/tab-skills.hbs b/src/templates/actor/character/tab-skills.hbs index 26c619c2..49203fec 100644 --- a/src/templates/actor/character/tab-skills.hbs +++ b/src/templates/actor/character/tab-skills.hbs @@ -2,8 +2,9 @@ data-tab="{{tabs.skills.id}}" data-group="{{tabs.skills.group}}">
-
-

Kampftalente

+
+
+

Kampftalente

    {{#each skills.Kampf}}
  • @@ -11,9 +12,11 @@
  • {{/each}}
+
-
-

Körperliche Talente

+
+
+

Körperliche Talente

  • {{#each skills.Körperlich}} @@ -22,9 +25,11 @@
  • {{/each}}
+
-
-

Gesellschaftliche Talente

+ -
-

Natur Talente

+
+
+

Natur Talente

  • {{#each skills.Natur}} @@ -44,9 +51,11 @@
  • {{/each}}
+
-
-

Wissenstalente

+
+
+

Wissenstalente

  • {{#each skills.Wissen}} @@ -55,9 +64,11 @@
  • {{/each}}
+
-
-

Schriften & Sprachen

+
+
+

Schriften & Sprachen

  • {{#each skills.Schriften}} @@ -71,9 +82,11 @@
  • {{/each}}
+
-
-

Handwerkliche Talente

+
+
+

Handwerkliche Talente

  • {{#each skills.Handwerk}} @@ -82,6 +95,7 @@
  • {{/each}}
+
\ No newline at end of file diff --git a/src/templates/ui/partial-rollable-button.hbs b/src/templates/ui/partial-rollable-button.hbs index 7007661b..ee575a8c 100644 --- a/src/templates/ui/partial-rollable-button.hbs +++ b/src/templates/ui/partial-rollable-button.hbs @@ -1,9 +1,5 @@ -
+
{{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} diff --git a/src/templates/ui/partial-rollable-language-button.hbs b/src/templates/ui/partial-rollable-language-button.hbs index 76027387..27c0e810 100644 --- a/src/templates/ui/partial-rollable-language-button.hbs +++ b/src/templates/ui/partial-rollable-language-button.hbs @@ -1,10 +1,7 @@ -
+
-
+
{{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} {{#if this.taw}} {{this.taw}} diff --git a/src/templates/ui/partial-rollable-weaponskill-button.hbs b/src/templates/ui/partial-rollable-weaponskill-button.hbs index 552ea31f..5225fbc8 100644 --- a/src/templates/ui/partial-rollable-weaponskill-button.hbs +++ b/src/templates/ui/partial-rollable-weaponskill-button.hbs @@ -1,11 +1,10 @@ -
+
{{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} - {{#if this.taw}} {{this.taw}} {{else}} -- 2.43.0 From 1bc6d9673af787484773aa98a1682c519249dbc6 Mon Sep 17 00:00:00 2001 From: macniel Date: Wed, 12 Nov 2025 20:42:29 +0100 Subject: [PATCH 08/24] inverts cooldown display, removes unintuitive progress/activate button and also fixes a bug in the tooltip --- src/lang/de.json | 4 +-- src/module/dialog/combatAction.mjs | 2 +- src/module/dialog/liturgyDialog.mjs | 2 +- src/module/sheets/character/combat.mjs | 4 ++- src/module/sheets/characterSheet.mjs | 18 +++++++--- src/style/atoms/_colours.scss | 4 +-- src/style/molecules/_sidebar-elements.scss | 33 +++++++------------ .../organisms/character-tabs/_inventory.scss | 2 +- src/templates/actor/character/main-sheet.hbs | 6 ++-- src/templates/ui/partial-cooldown.hbs | 27 +++++---------- 10 files changed, 46 insertions(+), 56 deletions(-) diff --git a/src/lang/de.json b/src/lang/de.json index b1914f86..164dc25c 100644 --- a/src/lang/de.json +++ b/src/lang/de.json @@ -20,9 +20,7 @@ } }, "COOLDOWN": { - "progress": "{t} weiter durchführen", - "cancel": "{t} abbrechen", - "activate": "{t} auslösen" + "cancel": "{t} abbrechen" }, "WEAPON": { "attack": "Mit {weapon} angreifen", diff --git a/src/module/dialog/combatAction.mjs b/src/module/dialog/combatAction.mjs index c89f0165..05eaae06 100644 --- a/src/module/dialog/combatAction.mjs +++ b/src/module/dialog/combatAction.mjs @@ -126,7 +126,7 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2 /** @type Cooldown */ const newCooldown = { start: maneuver.cooldown({weapon, skill, target, mod: this._mod}), - current: maneuver.cooldown({weapon, skill, target, mod: this._mod}), + current: 0, data: { cssClass: "Kampf", weapon: this._weaponId, diff --git a/src/module/dialog/liturgyDialog.mjs b/src/module/dialog/liturgyDialog.mjs index 7d7764d6..23fea809 100644 --- a/src/module/dialog/liturgyDialog.mjs +++ b/src/module/dialog/liturgyDialog.mjs @@ -163,7 +163,7 @@ export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) { } cooldowns.push({ start: castingTime, - current: castingTime, + current: 0, data: { cssClass: "Karmal", title: this._liturgy.name, diff --git a/src/module/sheets/character/combat.mjs b/src/module/sheets/character/combat.mjs index 10485d66..ff41d23c 100644 --- a/src/module/sheets/character/combat.mjs +++ b/src/module/sheets/character/combat.mjs @@ -26,9 +26,11 @@ export default { 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.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 return context diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index aaba9861..51e5ee86 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -153,7 +153,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { cooldowns.splice(cooldownId, 1) if (cooldown) { - cooldown.current = cooldown.current - 1 + cooldown.current = cooldown.current + 1 } cooldowns.push(cooldown) @@ -177,7 +177,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { const cooldowns = this.document.system.cooldowns const cooldown = this.document.system.cooldowns[cooldownId] - if (cooldown && cooldown.current <= 0) { + if (cooldown && cooldown.current >= cooldown.start) { const am = new ActionManager(this.document) console.log(cooldown.data.maneuver) const action = new Function(`return ${cooldown.data.maneuver}`) @@ -412,8 +412,11 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { 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 const fernkampf = actorData.findEquipmentOnSlot("fernkampf", actorData.system.setEquipped, actorData) const links = actorData.findEquipmentOnSlot("links", actorData.system.setEquipped, actorData) @@ -489,15 +492,20 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { let tooltip = cooldown.data.title if (cooldown.data.weapon) { weapon = this.document.itemTypes["Equipment"].find(p => p._id === cooldown.data.weapon) - tooltip += `
Waffe:${weapon.name}` + tooltip += `
Waffe: ${weapon.name}` } if (cooldown.data.target) { target = game.actors.get(game.scenes.current.tokens.find(p => p._id === cooldown.data.target).actorId) - tooltip += `
Waffe:${target.name}` + tooltip += `
Ziel: ${target.name}` } cooldown.title = cooldown.data.title cooldown.progress = ((cooldown.current / cooldown.start) * 100) + "%" - cooldown.tooltip = tooltip + `
Aktionen verbleibend: ${cooldown.current}` + if (cooldown.start - cooldown.current > 0) { + cooldown.tooltip = tooltip + `
Aktionen verbleibend: ${cooldown.start - cooldown.current}
: 1 Aktion aufwenden` + } else { + cooldown.tooltip = tooltip + `
Aktionen verbleibend: ${cooldown.start - cooldown.current}
: Aktion durchführen` + } + }) context.hasSpells = actorData.itemTypes["Spell"].length > 0 diff --git a/src/style/atoms/_colours.scss b/src/style/atoms/_colours.scss index 950f42d7..64689d04 100644 --- a/src/style/atoms/_colours.scss +++ b/src/style/atoms/_colours.scss @@ -1,12 +1,12 @@ $nachteil-color: #555753; $nachteil-text-color: #FFF; -$liturgie-color: #edd400; +$liturgie-color: #59aebf; $liturgie-text-color: #000; $zauber-color: #3465a4; $zauber-text-color: #000; $talent-color: #f57900; $talent-text-color: #000; -$kampftalent-color: #cc0000; +$kampftalent-color: #c36e14; $kampftalent-text-color: #FFF; $talent-body-color: #45d18c; diff --git a/src/style/molecules/_sidebar-elements.scss b/src/style/molecules/_sidebar-elements.scss index 7a696c23..62354506 100644 --- a/src/style/molecules/_sidebar-elements.scss +++ b/src/style/molecules/_sidebar-elements.scss @@ -11,7 +11,7 @@ width: 100%; position: relative; border: 1px inset #ccc; - background-color: rgba(0, 0, 0, 0.2); + background-color: rgba(0, 0, 0, 0.5); margin: 8px 0; label { @@ -19,8 +19,6 @@ left: 0; top: 0; bottom: 0; - width: 48px; - background-color: rgba(0, 0, 0, 0.1); z-index: 3; line-height: 24px; vertical-align: middle; @@ -226,22 +224,13 @@ position: absolute; background: url('/systems/DSA_4-1/assets/gradient.png'); background-size: 12px 100%; + background-blend-mode: overlay; + background-color: rgba(128, 0, 192, 1); left: 0; bottom: 0; top: 0; border-radius: 12px; z-index: 2; - - &::after { // progress fill - content: ''; - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - border-radius: 12px; - background-color: rgba(128, 0, 192, 0.5); - } } &::after { @@ -256,20 +245,20 @@ } - &.Kampf .progress::after { - background-color: rgba(colors.$kampftalent-color, 0.5); + &.Kampf .progress { + background-color: rgba(colors.$kampftalent-color, 1); } - &.Karmal .progress::after { - background-color: rgba(colors.$liturgie-color, 0.5); + &.Karmal .progress { + background-color: rgba(colors.$liturgie-color, 1); } - &.Magisch .progress::after { - background-color: rgba(colors.$zauber-color, 0.5); + &.Magisch .progress { + background-color: rgba(colors.$zauber-color, 1); } - &.Talent .progress::after { - background-color: rgba(colors.$talent-color, 0.5); + &.Talent .progress { + background-color: rgba(colors.$talent-color, 1); } } diff --git a/src/style/organisms/character-tabs/_inventory.scss b/src/style/organisms/character-tabs/_inventory.scss index 4a490e73..ecb35fb7 100644 --- a/src/style/organisms/character-tabs/_inventory.scss +++ b/src/style/organisms/character-tabs/_inventory.scss @@ -28,7 +28,7 @@ position: relative; border: 1px inset #ccc; background-color: rgba(0, 0, 0, 0.2); - height: 8px; + height: 16px; span.fill { position: absolute; diff --git a/src/templates/actor/character/main-sheet.hbs b/src/templates/actor/character/main-sheet.hbs index f4198f96..0af055ff 100644 --- a/src/templates/actor/character/main-sheet.hbs +++ b/src/templates/actor/character/main-sheet.hbs @@ -32,12 +32,14 @@ {{#if ausdauer}} {{/if}} diff --git a/src/templates/ui/partial-cooldown.hbs b/src/templates/ui/partial-cooldown.hbs index 199e05b7..d6cb26ee 100644 --- a/src/templates/ui/partial-cooldown.hbs +++ b/src/templates/ui/partial-cooldown.hbs @@ -1,23 +1,14 @@
- {{#if (gt this.current 0)}} - - {{this.title}} + {{this.title}} - {{else}} - - {{this.title}} - - {{/if}}
\ No newline at end of file +
\ No newline at end of file -- 2.43.0 From bbf181eb8caa4175c50655bb6b817b94400cc118 Mon Sep 17 00:00:00 2001 From: macniel Date: Thu, 13 Nov 2025 15:04:11 +0100 Subject: [PATCH 09/24] implements selecting an item and buying that if the coin is sufficent. --- src/module/dialog/itemBrowserDialog.mjs | 41 ++++++++++++++++++- src/style/organisms/_item-browser-dialog.scss | 5 +++ src/templates/dialog/item-browser-dialog.hbs | 8 +++- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/module/dialog/itemBrowserDialog.mjs b/src/module/dialog/itemBrowserDialog.mjs index dbad818b..21acf80c 100644 --- a/src/module/dialog/itemBrowserDialog.mjs +++ b/src/module/dialog/itemBrowserDialog.mjs @@ -22,6 +22,10 @@ export class ItemBrowserDialog extends HandlebarsApplicationMixin(ApplicationV2) window: { resizable: true, title: "Gegenstände Browser" + }, + actions: { + select: ItemBrowserDialog.#selectItem, + buy: ItemBrowserDialog.#buyItem } } @@ -42,6 +46,7 @@ export class ItemBrowserDialog extends HandlebarsApplicationMixin(ApplicationV2) * @private */ _items = [] + _selectedItem = null filter_price_lower = 0 filter_price_upper = 0 filter_weight_lower = 0 @@ -53,6 +58,7 @@ export class ItemBrowserDialog extends HandlebarsApplicationMixin(ApplicationV2) super(); this._actor = actor this._items = [] + this._selectedItem = null } static async #onSubmitForm(event, form, formData) { @@ -67,6 +73,37 @@ export class ItemBrowserDialog extends HandlebarsApplicationMixin(ApplicationV2) this.render({parts: ["form"]}) } + static async #selectItem(event, target) { + const {itemId} = target.dataset + const selectedItem = this._items.find(item => item.uuid === itemId) + + this._items?.forEach((item) => { + item.selected = item.uuid === itemId + }) + + if (selectedItem) { + this._selectedItem = selectedItem + } + this.render({parts: ["form"]}) + } + + static async #buyItem(event, target) { + if (this._actor && this._selectedItem) { + const canBuy = await this._actor.reduceWealth(this._selectedItem.price) + if (canBuy) { + const document = await foundry.utils.fromUuid(this._selectedItem.uuid) + if (document) { + await this._actor.createEmbeddedDocuments("Item", [document]) + ui.notifications.info(this._selectedItem.name + " wurde von " + this._actor.name + " gekauft") + } + } else { + ui.notifications.error(this._selectedItem.name + " ist zu teuer für " + this._actor.name) + } + + + } + } + _canDragDrop(event, options) { return game.user.isGM } @@ -117,6 +154,7 @@ export class ItemBrowserDialog extends HandlebarsApplicationMixin(ApplicationV2) context.price_upper = this._maxPrice context.weight_lower = this._minWeight context.weight_upper = this._maxWeight + context.hasSelectedItem = this._selectedItem != null context.items = this._items ?.filter(p => p.name.toLowerCase().indexOf(context.filterName.toLowerCase()) !== -1 || context.filterName === "") @@ -171,7 +209,8 @@ export class ItemBrowserDialog extends HandlebarsApplicationMixin(ApplicationV2) name: item.name, price: e.system.price, weight: e.system.weight, - category: e.system.category.join(", ") + category: e.system.category.join(", "), + selected: false, }) parsedEntries += 1 diff --git a/src/style/organisms/_item-browser-dialog.scss b/src/style/organisms/_item-browser-dialog.scss index 051979ba..9636d2df 100644 --- a/src/style/organisms/_item-browser-dialog.scss +++ b/src/style/organisms/_item-browser-dialog.scss @@ -84,6 +84,11 @@ &:nth-child(odd) { background-color: rgba(0, 0, 0, 0.1); } + + &.selected { + background-color: rgba(255, 140, 0, 0.2); + border: 1px solid orange; + } } } diff --git a/src/templates/dialog/item-browser-dialog.hbs b/src/templates/dialog/item-browser-dialog.hbs index 9dd575b3..b484a1f5 100644 --- a/src/templates/dialog/item-browser-dialog.hbs +++ b/src/templates/dialog/item-browser-dialog.hbs @@ -41,6 +41,11 @@ +
+ +
@@ -53,7 +58,8 @@
{{#each items}} -
+
{{this.name}} {{this.name}} {{this.category}} -- 2.43.0 From 47280f7216b31824447f56d94a551c5c41f9827b Mon Sep 17 00:00:00 2001 From: macniel Date: Thu, 13 Nov 2025 15:04:34 +0100 Subject: [PATCH 10/24] beginning operation:health. --- .../character/{combat.mjs => health.mjs} | 15 +++---- src/module/sheets/characterSheet.mjs | 14 +++---- src/style/organisms/_character-sheet.scss | 10 ++--- .../{_combat.scss => _health.scss} | 0 .../{tab-combat.hbs => tab-health.hbs} | 40 +++++++++---------- 5 files changed, 40 insertions(+), 39 deletions(-) rename src/module/sheets/character/{combat.mjs => health.mjs} (81%) rename src/style/organisms/character-tabs/{_combat.scss => _health.scss} (100%) rename src/templates/actor/character/{tab-combat.hbs => tab-health.hbs} (89%) diff --git a/src/module/sheets/character/combat.mjs b/src/module/sheets/character/health.mjs similarity index 81% rename from src/module/sheets/character/combat.mjs rename to src/module/sheets/character/health.mjs index ff41d23c..0e409976 100644 --- a/src/module/sheets/character/combat.mjs +++ b/src/module/sheets/character/health.mjs @@ -1,5 +1,3 @@ -import {ActionManager} from "../actions/action-manager.mjs"; - export default { _prepareContext: async (context, object) => { @@ -15,9 +13,6 @@ export default { return object.items.get(object.system.heldenausruestung[setNumber]?.[slot]) } - const am = new ActionManager(actorData) - context.actions = am.evaluate().filter(action => action.type !== ActionManager.ATTACK) - context.inidice = actorData.system.ini.wuerfel context.inivalue = actorData.system.ini.aktuell context.inimod = actorData.system.ini.mod @@ -32,6 +27,12 @@ export default { context.aspcurrent = actorData.system.asp.aktuell ?? 0 context.kapcurrent = actorData.system.kap.aktuell ?? 0 + context.effects = [] + for (let i = 0; i < actorData.appliedEffects.length; i++) { + const item = actorData.appliedEffects[i] + context.effects.push(item.name) + } + return context }, @@ -39,7 +40,7 @@ export default { }, _getTabConfig: (group) => { - group.tabs.push({id: "combat", group: "sheet", label: "Kampf"}) + group.tabs.push({id: "health", group: "sheet", label: "Gesundheit"}) }, - template: `systems/DSA_4-1/templates/actor/character/tab-combat.hbs` + template: `systems/DSA_4-1/templates/actor/character/tab-health.hbs` } \ No newline at end of file diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index 51e5ee86..2c8a6064 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -1,5 +1,5 @@ import Advsf from "./character/advsf.mjs" -import Combat from "./character/combat.mjs" +import Health from "./character/health.mjs" import Effects from "./character/effects.mjs" import Equipment from "./character/equipment.mjs" import Liturgies from "./character/liturgies.mjs" @@ -80,8 +80,8 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { advsf: { template: Advsf.template }, - combat: { - template: Combat.template + health: { + template: Health.template }, equipment: { template: Equipment.template, @@ -329,7 +329,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { Meta._getTabConfig(tabs, this) Social._getTabConfig(tabs, this) Advsf._getTabConfig(tabs, this) - Combat._getTabConfig(tabs, this) + Health._getTabConfig(tabs, this) Equipment._getTabConfig(tabs, this) Skills._getTabConfig(tabs, this) Spells._getTabConfig(tabs, this) @@ -572,8 +572,8 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { case "advsf": await Advsf._prepareContext(context, this.document) break - case "combat": - await Combat._prepareContext(context, this.document) + case "health": + await Health._prepareContext(context, this.document) break case "equipment": await Equipment._prepareContext(context, this.document, this) @@ -598,7 +598,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { Meta._onRender(context, options, this.element) Social._onRender(context, options, this.element) Advsf._onRender(context, options, this) - Combat._onRender(context, options, this.element) + Health._onRender(context, options, this.element) Effects._onRender(context, options, this.element) Equipment._onRender(context, options, this) Liturgies._onRender(context, options, this.element) diff --git a/src/style/organisms/_character-sheet.scss b/src/style/organisms/_character-sheet.scss index a653ed6f..4be1f8b5 100644 --- a/src/style/organisms/_character-sheet.scss +++ b/src/style/organisms/_character-sheet.scss @@ -5,7 +5,7 @@ @use "./character-tabs/social"; @use "./character-tabs/advsf"; @use "./character-tabs/inventory"; -@use "./character-tabs/combat"; +@use "./character-tabs/health"; @use "./character-tabs/spells"; @use "./character-tabs/liturgies"; @use "./character-tabs/skills"; @@ -95,8 +95,8 @@ @include inventory.tab; } - .tab.combat.active { - @include combat.tab; + .tab.health.active { + @include health.tab; } .tab.skills.active { @@ -135,8 +135,8 @@ @include inventory.tab(true); } - .tab.combat.active { - @include combat.tab(true); + .tab.health.active { + @include health.tab(true); } .tab.skills.active { diff --git a/src/style/organisms/character-tabs/_combat.scss b/src/style/organisms/character-tabs/_health.scss similarity index 100% rename from src/style/organisms/character-tabs/_combat.scss rename to src/style/organisms/character-tabs/_health.scss diff --git a/src/templates/actor/character/tab-combat.hbs b/src/templates/actor/character/tab-health.hbs similarity index 89% rename from src/templates/actor/character/tab-combat.hbs rename to src/templates/actor/character/tab-health.hbs index 67511b0f..2d49e510 100644 --- a/src/templates/actor/character/tab-combat.hbs +++ b/src/templates/actor/character/tab-health.hbs @@ -1,7 +1,6 @@ -
- +
@@ -55,23 +54,25 @@
{{/if}} +
+ +
-
-

Aktionen im Kampf

-
-
- Angriff - variabel -
-
- Verteidigen - variabel -
+
+ +
- {{#each this.actions}} - {{> "systems/DSA_4-1/templates/ui/partial-action-button.hbs" this}} - {{/each}} -
+
+ +
    + {{#each effects}} +
  • {{this}}
  • + {{/each}} +
{{#if (or trefferzonen zonenruestung)}} @@ -111,5 +112,4 @@
{{/if}} -
-- 2.43.0 From 6d366188ead2a6cc461fd1a1d6d97967bdaec461 Mon Sep 17 00:00:00 2001 From: macniel Date: Thu, 13 Nov 2025 22:40:48 +0100 Subject: [PATCH 11/24] begins implementing sidebar elements for pinned Items --- src/module/setup/partials.mjs | 7 ++- src/module/sheets/character/advsf.mjs | 7 ++- src/module/sheets/character/liturgies.mjs | 1 + src/module/sheets/character/skills.mjs | 3 +- src/module/sheets/character/spells.mjs | 1 + src/module/sheets/characterSheet.mjs | 59 ++++++++++++++++++- src/style/molecules/_rollable.scss | 48 +++++++++------ src/templates/actor/character/main-sheet.hbs | 7 +++ src/templates/actor/character/tab-spells.hbs | 11 +++- src/templates/item/spell/tab-commonality.hbs | 4 +- src/templates/item/spell/tab-meta.hbs | 10 ++-- src/templates/item/spell/tab-variants.hbs | 4 +- .../ui/partial-mini-rollable-button.hbs | 3 + .../partial-mini-rollable-language-button.hbs | 3 + .../partial-mini-rollable-liturgy-button.hbs | 3 + .../ui/partial-mini-rollable-spell-button.hbs | 3 + ...rtial-mini-rollable-weaponskill-button.hbs | 7 +++ src/templates/ui/partial-rollable-button.hbs | 7 +++ .../ui/partial-rollable-language-button.hbs | 7 +++ .../partial-rollable-weaponskill-button.hbs | 7 +++ 20 files changed, 170 insertions(+), 32 deletions(-) create mode 100644 src/templates/ui/partial-mini-rollable-button.hbs create mode 100644 src/templates/ui/partial-mini-rollable-language-button.hbs create mode 100644 src/templates/ui/partial-mini-rollable-liturgy-button.hbs create mode 100644 src/templates/ui/partial-mini-rollable-spell-button.hbs create mode 100644 src/templates/ui/partial-mini-rollable-weaponskill-button.hbs diff --git a/src/module/setup/partials.mjs b/src/module/setup/partials.mjs index f589948e..ce3115dd 100644 --- a/src/module/setup/partials.mjs +++ b/src/module/setup/partials.mjs @@ -16,7 +16,12 @@ function loadPartials(hbs) { 'systems/DSA_4-1/templates/ui/partial-equipment-button.hbs', 'systems/DSA_4-1/templates/ui/partial-array-editor.hbs', 'systems/DSA_4-1/templates/actor/character/tab-set.hbs', - 'systems/DSA_4-1/templates/dialog/liturgy-dialog.hbs' + 'systems/DSA_4-1/templates/dialog/liturgy-dialog.hbs', + 'systems/DSA_4-1/templates/ui/partial-mini-rollable-button.hbs', + 'systems/DSA_4-1/templates/ui/partial-mini-rollable-liturgy-button.hbs', + 'systems/DSA_4-1/templates/ui/partial-mini-rollable-weaponskill-button.hbs', + 'systems/DSA_4-1/templates/ui/partial-mini-rollable-language-button.hbs', + 'systems/DSA_4-1/templates/ui/partial-mini-rollable-spell-button.hbs', ]).then(resolve); }) diff --git a/src/module/sheets/character/advsf.mjs b/src/module/sheets/character/advsf.mjs index f0074d84..2bd10a79 100644 --- a/src/module/sheets/character/advsf.mjs +++ b/src/module/sheets/character/advsf.mjs @@ -21,7 +21,8 @@ export default { description: item.system.description, isAdvantage: !item.system.nachteil, isDisadvantage: item.system.nachteil, - isBadAttribute: item.system.schlechteEigenschaft + isBadAttribute: item.system.schlechteEigenschaft, + fav: item.getFlag("DSA_4-1", "favourite") }) } else { context.flaws.push({ @@ -32,7 +33,8 @@ export default { description: item.system.description, isAdvantage: !item.system.nachteil, isDisadvantage: item.system.nachteil, - isBadAttribute: item.system.schlechteEigenschaft + isBadAttribute: item.system.schlechteEigenschaft, + fav: item.getFlag("DSA_4-1", "favourite") }) } } @@ -43,6 +45,7 @@ export default { context.specialAbilities.push({ id: item._id, name: item.system.value ? item.system.value : item.name, + fav: item.getFlag("DSA_4-1", "favourite") }); } ); diff --git a/src/module/sheets/character/liturgies.mjs b/src/module/sheets/character/liturgies.mjs index c5293522..ac5022c8 100644 --- a/src/module/sheets/character/liturgies.mjs +++ b/src/module/sheets/character/liturgies.mjs @@ -68,6 +68,7 @@ export default { lkpReq: lkp, lkpMod: mod, costKaP, + fav: item.getFlag("DSA_4-1", "favourite"), rank: index, // get effective liturgy rank based on deity liturgiekenntnis: deity, }) diff --git a/src/module/sheets/character/skills.mjs b/src/module/sheets/character/skills.mjs index 9cf1d9d5..8c868d44 100644 --- a/src/module/sheets/character/skills.mjs +++ b/src/module/sheets/character/skills.mjs @@ -51,7 +51,8 @@ export default { id: item._id, at: item.system.at, pa: item.system.pa, - komplexität: item.system.komplexität + komplexität: item.system.komplexität, + fav: item.getFlag("DSA_4-1", "favourite") }; if (talentGruppe === "Kampf") { diff --git a/src/module/sheets/character/spells.mjs b/src/module/sheets/character/spells.mjs index 917679be..db409ba5 100644 --- a/src/module/sheets/character/spells.mjs +++ b/src/module/sheets/character/spells.mjs @@ -42,6 +42,7 @@ export default { eigenschaft1: werte[0].name, eigenschaft2: werte[1].name, eigenschaft3: werte[2].name, + fav: item.getFlag("DSA_4-1", "favourite") }) }) diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index 2c8a6064..fad3b1de 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -47,6 +47,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { openSpeciesDocument: CharacterSheet.#openSpeciesDocument, openCombatAction: CharacterSheet.#openCombatAction, openLiturgyDialog: CharacterSheet.#openLiturgyDialog, + openSpellDialog: CharacterSheet.#openSpellDialog, progressCooldown: CharacterSheet.#progressCooldown, cancelCooldown: CharacterSheet.#cancelCooldown, activateCooldown: CharacterSheet.#activateCooldown, @@ -54,7 +55,8 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { removeEffect: CharacterSheet.#removeEffect, rollDamage: CharacterSheet.#rollDamage, openItemBrowser: CharacterSheet.#openItemBrowser, - newItem: CharacterSheet.#addNewItem + newItem: CharacterSheet.#addNewItem, + toggleFav: CharacterSheet.#toggleFav, } } @@ -233,6 +235,12 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { new LiturgyDialog(this.document, lkp, id, deity).render(true) } + static #openSpellDialog(event, target) { + const {itemId} = target.dataset + console.log(itemId) + this.document.itemTypes["Spell"]?.find(p => p.id === itemId)?.sheet.render(true) + } + static #startResting(event, target) { const dialog = new RestingDialog(this.document) @@ -267,6 +275,16 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { items[0].sheet.render(true) } + static async #toggleFav(event, target) { + const {itemId} = target.dataset + const doc = this.document.items.find(p => p.id === itemId) + + if (doc) { + const previous = doc.getFlag("DSA_4-1", "favourite") ?? false + doc.setFlag("DSA_4-1", "favourite", !previous) + } + } + _configureRenderOptions(options) { super._configureRenderOptions(options) @@ -277,6 +295,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { return options } + /** * Handle form submission * @this {AdvantageSheet} @@ -485,6 +504,44 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { }) } + context.favourites = actorData.items.filter(item => item.getFlag("DSA_4-1", "favourite") === true).map(item => { + let id = item.id + let t = null + switch (item.type) { + case "Spell": + t = "systems/DSA_4-1/templates/ui/partial-mini-rollable-spell-button.hbs" + break; + case "Skill": + switch (item.system.gruppe) { + case "Kampf": + t = "systems/DSA_4-1/templates/ui/partial-mini-rollable-weaponskill-button.hbs" + break; + case "Sprachen": + t = "systems/DSA_4-1/templates/ui/partial-mini-rollable-language-button.hbs" + break; + default: + t = "systems/DSA_4-1/templates/ui/partial-mini-rollable-button.hbs" + } + break; + case "Liturgy": + t = "systems/DSA_4-1/templates/ui/partial-mini-rollable-liturgy-button.hbs" + break; + default: + t = null + } + + let obj = Object.assign({}, item) + + obj.fav = item.getFlag("DSA_4-1", "favourite") + obj.id = id + + if (t) { + obj.template = t + } + + return obj + }) + context.cooldowns = actorData.system.cooldowns ?? [] context.cooldowns.forEach(cooldown => { let weapon = null diff --git a/src/style/molecules/_rollable.scss b/src/style/molecules/_rollable.scss index 642d23bd..69b30a92 100644 --- a/src/style/molecules/_rollable.scss +++ b/src/style/molecules/_rollable.scss @@ -36,7 +36,7 @@ $rollable_colours_font: ( display: block; height: 32px; position: relative; - margin: 4px; + margin: 4px 32px 4px 4px; .die { width: 32px; @@ -69,6 +69,24 @@ $rollable_colours_font: ( top: 6px; } } + + &:active { + + + scale: 0.8; + + .value { + + img { + position: absolute; + width: 20px; + height: 20px; + left: 4px; + top: 7px; + } + } + + } } .container { @@ -122,6 +140,18 @@ $rollable_colours_font: ( } } } + + .outside { + position: absolute; + right: -24px; + top: 8px; + bottom: 8px; + z-index: 3; + + &:hover { + text-shadow: 0 0 10px rgb(255 0 0); + } + } } // interactivity @@ -135,23 +165,7 @@ $rollable_colours_font: ( } - &:active { - .die { - scale: 0.8; - - .value { - - img { - position: absolute; - width: 20px; - height: 20px; - left: 4px; - top: 7px; - } - } - } - } } } diff --git a/src/templates/actor/character/main-sheet.hbs b/src/templates/actor/character/main-sheet.hbs index 0af055ff..386fc6b9 100644 --- a/src/templates/actor/character/main-sheet.hbs +++ b/src/templates/actor/character/main-sheet.hbs @@ -99,6 +99,13 @@
{{/each}} +
+

Angepinnt

+ {{#each this.favourites}} + {{> (lookup this "template") this}} + {{/each}} +
+

Abklingzeiten

{{#each this.cooldowns}} diff --git a/src/templates/actor/character/tab-spells.hbs b/src/templates/actor/character/tab-spells.hbs index 46ec9463..1b6e8a1e 100644 --- a/src/templates/actor/character/tab-spells.hbs +++ b/src/templates/actor/character/tab-spells.hbs @@ -33,7 +33,7 @@ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} - + {{this.name}} {{this.eigenschaft1}} {{this.eigenschaft2}} @@ -43,6 +43,15 @@
    {{#each this.merkmal}}
  • {{this}}
  • {{/each}}
+ +
+ {{#if this.fav}} + + {{else}} + + {{/if}} +
+ {{/each}} diff --git a/src/templates/item/spell/tab-commonality.hbs b/src/templates/item/spell/tab-commonality.hbs index 351998d0..89a6a8d5 100644 --- a/src/templates/item/spell/tab-commonality.hbs +++ b/src/templates/item/spell/tab-commonality.hbs @@ -1,7 +1,7 @@
- +
- +
\ No newline at end of file diff --git a/src/templates/item/spell/tab-meta.hbs b/src/templates/item/spell/tab-meta.hbs index 7dc4079b..211cdaee 100644 --- a/src/templates/item/spell/tab-meta.hbs +++ b/src/templates/item/spell/tab-meta.hbs @@ -1,11 +1,11 @@
- +
@@ -14,7 +14,7 @@ value="{{system.probe.[0]}}"/> -
@@ -44,5 +44,5 @@
- +
\ No newline at end of file diff --git a/src/templates/item/spell/tab-variants.hbs b/src/templates/item/spell/tab-variants.hbs index 334d3786..c382c66d 100644 --- a/src/templates/item/spell/tab-variants.hbs +++ b/src/templates/item/spell/tab-variants.hbs @@ -1,7 +1,7 @@
- +
- +
\ No newline at end of file diff --git a/src/templates/ui/partial-mini-rollable-button.hbs b/src/templates/ui/partial-mini-rollable-button.hbs new file mode 100644 index 00000000..7dd171ee --- /dev/null +++ b/src/templates/ui/partial-mini-rollable-button.hbs @@ -0,0 +1,3 @@ +
+ {{this.name}} +
\ No newline at end of file diff --git a/src/templates/ui/partial-mini-rollable-language-button.hbs b/src/templates/ui/partial-mini-rollable-language-button.hbs new file mode 100644 index 00000000..7fb3506c --- /dev/null +++ b/src/templates/ui/partial-mini-rollable-language-button.hbs @@ -0,0 +1,3 @@ +
+ {{this.name}} +
\ No newline at end of file diff --git a/src/templates/ui/partial-mini-rollable-liturgy-button.hbs b/src/templates/ui/partial-mini-rollable-liturgy-button.hbs new file mode 100644 index 00000000..e032c98a --- /dev/null +++ b/src/templates/ui/partial-mini-rollable-liturgy-button.hbs @@ -0,0 +1,3 @@ +
+ {{this.name}} +
\ No newline at end of file diff --git a/src/templates/ui/partial-mini-rollable-spell-button.hbs b/src/templates/ui/partial-mini-rollable-spell-button.hbs new file mode 100644 index 00000000..da472975 --- /dev/null +++ b/src/templates/ui/partial-mini-rollable-spell-button.hbs @@ -0,0 +1,3 @@ +
+ {{this.name}} +
\ No newline at end of file diff --git a/src/templates/ui/partial-mini-rollable-weaponskill-button.hbs b/src/templates/ui/partial-mini-rollable-weaponskill-button.hbs new file mode 100644 index 00000000..aabced0f --- /dev/null +++ b/src/templates/ui/partial-mini-rollable-weaponskill-button.hbs @@ -0,0 +1,7 @@ +
+
+ {{this.name}} +
+
\ No newline at end of file diff --git a/src/templates/ui/partial-rollable-button.hbs b/src/templates/ui/partial-rollable-button.hbs index ee575a8c..dcfe6edc 100644 --- a/src/templates/ui/partial-rollable-button.hbs +++ b/src/templates/ui/partial-rollable-button.hbs @@ -21,4 +21,11 @@ {{/each}}
+
+ {{#if this.fav}} + + {{else}} + + {{/if}} +
diff --git a/src/templates/ui/partial-rollable-language-button.hbs b/src/templates/ui/partial-rollable-language-button.hbs index 27c0e810..b4196107 100644 --- a/src/templates/ui/partial-rollable-language-button.hbs +++ b/src/templates/ui/partial-rollable-language-button.hbs @@ -23,4 +23,11 @@ {{/each}}
+
+ {{#if this.fav}} + + {{else}} + + {{/if}} +
diff --git a/src/templates/ui/partial-rollable-weaponskill-button.hbs b/src/templates/ui/partial-rollable-weaponskill-button.hbs index 5225fbc8..fe7648dd 100644 --- a/src/templates/ui/partial-rollable-weaponskill-button.hbs +++ b/src/templates/ui/partial-rollable-weaponskill-button.hbs @@ -24,4 +24,11 @@ {{/if}}
+
+ {{#if this.fav}} + + {{else}} + + {{/if}} +
-- 2.43.0 From 0fffebdab9a19c8ac587177df7ad5446b66caed1 Mon Sep 17 00:00:00 2001 From: macniel Date: Fri, 14 Nov 2025 00:07:31 +0100 Subject: [PATCH 12/24] implements mini character sheet, now it also needs tabs on the side to open dedicated sections from the big boy character sheet as dialogs. --- src/module/sheets/characterSheet.mjs | 9 +++++ src/style/organisms/_character-sheet.scss | 40 +++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index fad3b1de..4876b906 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -651,6 +651,15 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { return context } + _onPosition(position) { + + if (position.width < 300) { + this.element.classList.add("tiny") + } else { + this.element.classList.remove("tiny") + } + } + _onRender(context, options) { Meta._onRender(context, options, this.element) Social._onRender(context, options, this.element) diff --git a/src/style/organisms/_character-sheet.scss b/src/style/organisms/_character-sheet.scss index 4be1f8b5..163ef47b 100644 --- a/src/style/organisms/_character-sheet.scss +++ b/src/style/organisms/_character-sheet.scss @@ -113,6 +113,46 @@ } + &.tiny { + + .header-fields { + & > div:not(.attributes) { + display: none; + } + + & > div.attributes { + position: absolute; + left: -8px; + top: -8px; + right: -8px; + display: grid; + gap: 8px; + grid-template-columns: repeat(4, 1fr); + } + + } + + div.head-data { + width: unset; + top: 136px; + left: 8px; + right: 8px; + bottom: 8px; + + .profile-img { + justify-self: center; + } + } + + .sheet-tabs { + display: none; + } + + section.tab.tab.tab { + display: none; + } + } + } .theme-dark { -- 2.43.0 From accd2d1f16c5710bee0ad0ba3a75d44ea78690ea Mon Sep 17 00:00:00 2001 From: macniel Date: Fri, 14 Nov 2025 15:57:07 +0100 Subject: [PATCH 13/24] continues development on mini character sheet --- .../sheets/character-standalone/advsf.mjs | 118 ++++++++++++++++ .../sheets/character-standalone/bagpack.mjs | 98 ++++++++++++++ .../sheets/character-standalone/skills.mjs | 127 ++++++++++++++++++ src/module/sheets/character/skills.mjs | 1 - src/module/sheets/characterSheet.mjs | 61 +++++++-- src/style/atoms/_typography.scss | 1 + src/style/molecules/_sidebar-elements.scss | 27 ++++ src/style/organisms/_character-sheet.scss | 28 +++- .../organisms/character-tabs/_advsf.scss | 8 ++ .../organisms/character-tabs/_inventory.scss | 49 +++++++ .../organisms/character-tabs/_skills.scss | 14 ++ src/templates/actor/character/main-sheet.hbs | 13 ++ .../actor/character/standalone/advsf.hbs | 26 ++++ .../actor/character/standalone/bagpack.hbs | 20 +++ .../actor/character/standalone/skills.hbs | 97 +++++++++++++ 15 files changed, 672 insertions(+), 16 deletions(-) create mode 100644 src/module/sheets/character-standalone/advsf.mjs create mode 100644 src/module/sheets/character-standalone/bagpack.mjs create mode 100644 src/module/sheets/character-standalone/skills.mjs create mode 100644 src/templates/actor/character/standalone/advsf.hbs create mode 100644 src/templates/actor/character/standalone/bagpack.hbs create mode 100644 src/templates/actor/character/standalone/skills.hbs diff --git a/src/module/sheets/character-standalone/advsf.mjs b/src/module/sheets/character-standalone/advsf.mjs new file mode 100644 index 00000000..11777bbf --- /dev/null +++ b/src/module/sheets/character-standalone/advsf.mjs @@ -0,0 +1,118 @@ +const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api +const {ActorSheetV2} = foundry.applications.sheets + +export class StandaloneADVSF extends HandlebarsApplicationMixin(ActorSheetV2) { + + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + position: {width: 520, height: 480}, + classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'advsf'], + tag: 'form', + actions: { + rollFlaw: StandaloneADVSF.#rollFlaw, + openEmbeddedDocument: StandaloneADVSF.#openEmbeddedDocument, + + } + } + + /** @inheritDoc */ + static PARTS = { + form: { + template: `systems/DSA_4-1/templates/actor/character/standalone/advsf.hbs` + } + } + + _actor = null + + constructor(actor) { + super(actor) + this._actor = actor + this.render(true) + this.options.window.title = `${this.document.name} Vor und Nachteile` + } + + static async #rollFlaw(event, target) { + this._actor?.sheet.options.actions.rollFlaw.bind(this)(event, target) + } + + static async #openEmbeddedDocument(event, target) { + this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target) + } + + _configureRenderOptions(options) { + super._configureRenderOptions(options) + + options.window.title = `${this.document.name}: Vor und Nachteile` + + return options + } + + async _prepareContext(context, options, object) { + if (this._actor) { + const actorData = this.document + context.system = actorData.system + context.flags = actorData.flags + context.derived = actorData.system + context.originalName = actorData.name + context.name = context.derived.name ?? actorData.name + context.effects = actorData.effects ?? [] + context.advantages = [] + context.flaws = [] + + actorData.itemTypes.Advantage.forEach((item) => { + if (!item.system.schlechteEigenschaft) { + context.advantages.push({ + id: item._id, + name: item.name, + value: item.system.value, + options: item.system.auswahl, + description: item.system.description, + isAdvantage: !item.system.nachteil, + isDisadvantage: item.system.nachteil, + isBadAttribute: item.system.schlechteEigenschaft, + fav: item.getFlag("DSA_4-1", "favourite") + }) + } else { + context.flaws.push({ + id: item._id, + name: item.name, + value: item.system.value, + options: item.system.auswahl, + description: item.system.description, + isAdvantage: !item.system.nachteil, + isDisadvantage: item.system.nachteil, + isBadAttribute: item.system.schlechteEigenschaft, + fav: item.getFlag("DSA_4-1", "favourite") + }) + } + } + ) + + context.specialAbilities = [] + actorData.itemTypes.SpecialAbility.forEach((item) => { + context.specialAbilities.push({ + id: item._id, + name: item.system.value ? item.system.value : item.name, + fav: item.getFlag("DSA_4-1", "favourite") + }); + } + ); + + return context + } + } + + _onRender(context, options) { + if (this._actor) { + new foundry.applications.ux.DragDrop.implementation({ + dropSelector: ".advantages, .special-abilities", + permissions: { + drop: this._actor.sheet._canDragDrop.bind(this._actor.sheet) + }, + callbacks: { + drop: this._actor.sheet._onDrop.bind(this._actor.sheet), + } + }).bind(this.element); + } + } +} \ No newline at end of file diff --git a/src/module/sheets/character-standalone/bagpack.mjs b/src/module/sheets/character-standalone/bagpack.mjs new file mode 100644 index 00000000..24a52224 --- /dev/null +++ b/src/module/sheets/character-standalone/bagpack.mjs @@ -0,0 +1,98 @@ +const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api +const {ActorSheetV2} = foundry.applications.sheets + +export class Bagpack extends HandlebarsApplicationMixin(ActorSheetV2) { + + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + position: {width: 520, height: 480}, + classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'bagpack'], + tag: 'form', + actions: { + openItemBrowser: Bagpack.#openItemBrowser, + newItem: Bagpack.#newItem, + openEmbeddedDocument: Bagpack.#openEmbeddedDocument, + + } + } + + /** @inheritDoc */ + static PARTS = { + form: { + template: `systems/DSA_4-1/templates/actor/character/standalone/bagpack.hbs` + } + } + + _actor = null + + constructor(actor) { + super(actor) + this._actor = actor + this.render(true) + } + + static async #openItemBrowser(event, target) { + this._actor?.sheet.options.actions.openItemBrowser().bind(this)(event, target) + } + + static async #newItem(event, target) { + this._actor?.sheet.options.actions.newItem.bind(this)(event, target) + } + + static async #openEmbeddedDocument(event, target) { + this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target) + } + + _configureRenderOptions(options) { + super._configureRenderOptions(options) + + options.window.title = `${this.document.name}: Inventar` + + return options + } + + async _prepareContext(context, options, object) { + const actorData = this.document + context.system = actorData.system + context.flags = actorData.flags + + context.equipments = [] + context.carryingweight = 0 + actorData.itemTypes["Equipment"].sort((a, b) => a.sort - b.sort).forEach((item, index) => { + + // worn items are halved weight + + let effectiveWeight = item.system.weight ?? 0 + if (this.document.isWorn(item._id)) { + effectiveWeight = item.system.weight ? item.system.weight / 2 : 0 + } + + context.equipments.push({ + index: index, + id: item._id, + quantity: item.system.quantity, + name: item.name, + icon: item.img ?? "", + weight: item.system.weight, + worn: this.document.isWorn(item._id) + }) + context.carryingweight += item.system.quantity * effectiveWeight; + + }) + context.maxcarryingcapacity = actorData.system.attribute.kk.aktuell + context.carryingpercentage = Math.min((context.carryingweight / context.maxcarryingcapacity) * 100, 100); + + context.wealth = 0 + + actorData.itemTypes["Equipment"].forEach(coin => { + if (coin.system.category.indexOf("Währung") !== -1) { + context.wealth += (coin.system.quantity * coin.system.currencyDenominator) + } + }) + + return context + } + + _onRender(context, options) { + } +} \ No newline at end of file diff --git a/src/module/sheets/character-standalone/skills.mjs b/src/module/sheets/character-standalone/skills.mjs new file mode 100644 index 00000000..7d752bb6 --- /dev/null +++ b/src/module/sheets/character-standalone/skills.mjs @@ -0,0 +1,127 @@ +const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api +const {ActorSheetV2} = foundry.applications.sheets + +export class StandaloneSkills extends HandlebarsApplicationMixin(ActorSheetV2) { + + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + position: {width: 520, height: 480}, + classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'skills'], + tag: 'form', + actions: { + rollCombatSkill: StandaloneSkills.#rollCombatSkill, + rollSkill: StandaloneSkills.#rollSkill, + openEmbeddedDocument: StandaloneSkills.#openEmbeddedDocument, + + } + } + + /** @inheritDoc */ + static PARTS = { + form: { + template: `systems/DSA_4-1/templates/actor/character/standalone/skills.hbs` + } + } + + _actor = null + + constructor(actor) { + super(actor) + this._actor = actor + this.render(true) + } + + static async #rollCombatSkill(event, target) { + this._actor?.sheet.options.actions.rollCombatSkill.bind(this)(event, target) + } + + static async #rollSkill(event, target) { + this._actor?.sheet.options.actions.rollSkill.bind(this)(event, target) + } + + static async #openEmbeddedDocument(event, target) { + this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target) + } + + _configureRenderOptions(options) { + super._configureRenderOptions(options) + + options.window.title = `${this.document.name}: Talente` + + 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 prepareEigenschaftRoll = (actorData, name) => { + if (name && name !== "*") { + return actorData.system.attribute[name.toLowerCase()].aktuell + } else { + return 0 + } + } + + context.skills = {}; + context.flatSkills = []; + + actorData.itemTypes.Skill.forEach((item, index) => { + + const talentGruppe = item.system.gruppe; + const eigenschaften = Object.values(item.system.probe); + const werte = [ + {name: eigenschaften[0], value: prepareEigenschaftRoll(actorData, eigenschaften[0])}, + {name: eigenschaften[1], value: prepareEigenschaftRoll(actorData, eigenschaften[1])}, + {name: eigenschaften[2], value: prepareEigenschaftRoll(actorData, eigenschaften[2])} + ] + if (context.skills[talentGruppe] == null) { + context.skills[talentGruppe] = []; + } + const obj = { + type: "talent", + gruppe: talentGruppe, + name: item.name.replace(/Sprachen kennen/g, "Sprache:").replace(/Lesen\/Schreiben/g, "Schrift: "), + taw: "" + item.system.taw, + tawPath: `system.items.${index}.taw`, + werte, + rollEigenschaft1: werte[0].value, + rollEigenschaft2: werte[1].value, + rollEigenschaft3: werte[2].value, + eigenschaft1: werte[0].name, + eigenschaft2: werte[1].name, + eigenschaft3: werte[2].name, + probe: `(${eigenschaften.join("/")})`, + id: item._id, + at: item.system.at, + pa: item.system.pa, + komplexität: item.system.komplexität, + fav: item.getFlag("DSA_4-1", "favourite") + }; + + if (talentGruppe === "Kampf") { + + if (item.system.pa != null) { // has no parry value so it must be ranged talent (TODO: but it isnt as there can be combatstatistics which has no pa value assigned to) + obj.at = item.system.at + context.derived.at.aktuell + obj.pa = item.system.pa + context.derived.pa.aktuell + } else { + obj.at = item.system.at + context.derived.fk.aktuell + } + } + + context.skills[talentGruppe].push(obj); + context.flatSkills.push(obj); + } + ) + + return context + } + + _onRender(context, options) { + } +} \ No newline at end of file diff --git a/src/module/sheets/character/skills.mjs b/src/module/sheets/character/skills.mjs index 8c868d44..319f1f58 100644 --- a/src/module/sheets/character/skills.mjs +++ b/src/module/sheets/character/skills.mjs @@ -2,7 +2,6 @@ export default { _prepareContext: (context) => { const actorData = context.document - context.spells = [] context.system = actorData.system context.flags = actorData.flags context.derived = context.document.system diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index 4876b906..91457d1a 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -16,6 +16,9 @@ import {TalentDialog} from "../dialog/talentDialog.mjs"; import {AttributeDialog} from "../dialog/attributeDialog.mjs"; import {ItemBrowserDialog} from "../dialog/itemBrowserDialog.mjs"; import * as EquipmentDocument from "../documents/equipment.mjs"; +import {StandaloneADVSF} from "./character-standalone/advsf.mjs"; +import {StandaloneSkills} from "./character-standalone/skills.mjs"; +import {Bagpack} from "./character-standalone/bagpack.mjs"; const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api const {ActorSheetV2} = foundry.applications.sheets @@ -39,24 +42,27 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { actions: { rollCombatSkill: CharacterSheet.#rollCombatSkill, rollSkill: CharacterSheet.#rollSkill, - rollFlaw: CharacterSheet.#rollFlaw, + rollFlaw: CharacterSheet.rollFlaw, rollAttribute: CharacterSheet.#rollAttribute, editImage: DocumentSheetV2.DEFAULT_OPTIONS.actions.editImage, - openEmbeddedDocument: CharacterSheet.#openEmbeddedDocument, + openEmbeddedDocument: CharacterSheet.openEmbeddedDocument, openCultureDocument: CharacterSheet.#openCultureDocument, openSpeciesDocument: CharacterSheet.#openSpeciesDocument, openCombatAction: CharacterSheet.#openCombatAction, - openLiturgyDialog: CharacterSheet.#openLiturgyDialog, - openSpellDialog: CharacterSheet.#openSpellDialog, + openLiturgyDialog: CharacterSheet.openLiturgyDialog, + openSpellDialog: CharacterSheet.openSpellDialog, progressCooldown: CharacterSheet.#progressCooldown, cancelCooldown: CharacterSheet.#cancelCooldown, activateCooldown: CharacterSheet.#activateCooldown, rest: CharacterSheet.#startResting, removeEffect: CharacterSheet.#removeEffect, rollDamage: CharacterSheet.#rollDamage, - openItemBrowser: CharacterSheet.#openItemBrowser, - newItem: CharacterSheet.#addNewItem, - toggleFav: CharacterSheet.#toggleFav, + openItemBrowser: CharacterSheet.openItemBrowser, + newItem: CharacterSheet.addNewItem, + toggleFav: CharacterSheet.toggleFav, + openStandaloneADVSF: CharacterSheet.#openStandaloneADVSF, + openStandaloneSkills: CharacterSheet.#openStandaloneSkills, + openBagpack: CharacterSheet.#openBagpack } } @@ -144,7 +150,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { }).render(true) } - static async #rollFlaw(event, target) { + static async rollFlaw(event, target) { new AttributeDialog(this.document, target.dataset.itemId).render(true) } @@ -199,7 +205,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { * * @param {MouseEvent} event */ - static #openEmbeddedDocument(event) { + static openEmbeddedDocument(event) { let dataset = event.target.dataset if (!dataset.itemId && !dataset.id) { dataset = event.target.parentElement.dataset @@ -230,12 +236,12 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { } } - static #openLiturgyDialog(event, target) { + static openLiturgyDialog(event, target) { const {id, lkp, deity} = target.dataset new LiturgyDialog(this.document, lkp, id, deity).render(true) } - static #openSpellDialog(event, target) { + static openSpellDialog(event, target) { const {itemId} = target.dataset console.log(itemId) this.document.itemTypes["Spell"]?.find(p => p.id === itemId)?.sheet.render(true) @@ -262,11 +268,11 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { } - static async #openItemBrowser(event, target) { + static async openItemBrowser(event, target) { new ItemBrowserDialog(this.document).render(true) } - static async #addNewItem(event, target) { + static async addNewItem(event, target) { let item = new EquipmentDocument.Equipment({ name: "Neuer Gegenstand", type: "Equipment", @@ -275,7 +281,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { items[0].sheet.render(true) } - static async #toggleFav(event, target) { + static async toggleFav(event, target) { const {itemId} = target.dataset const doc = this.document.items.find(p => p.id === itemId) @@ -285,6 +291,30 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { } } + static async #openStandaloneADVSF(event, target) { + new StandaloneADVSF(this.document) + } + + static async #openStandaloneHealth(event, target) { + new StandaloneHealth(this.document) + } + + static async #openStandaloneSkills(event, target) { + new StandaloneSkills(this.document) + } + + static async #openBagpack(event, target) { + new Bagpack(this.document) + } + + static async #openStandaloneSpells(event, target) { + new StandaloneSpells(this.document) + } + + static async #openStandaloneLiturgies(event, target) { + new StandaloneLiturgies(this.document) + } + _configureRenderOptions(options) { super._configureRenderOptions(options) @@ -655,9 +685,12 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { if (position.width < 300) { this.element.classList.add("tiny") + this.element.querySelector(".sidebuttons").style.left = (position.width + position.left) + "px" + this.element.querySelector(".sidebuttons").style.top = (position.top) + "px" } else { this.element.classList.remove("tiny") } + } _onRender(context, options) { diff --git a/src/style/atoms/_typography.scss b/src/style/atoms/_typography.scss index a56c325e..ca5c1f46 100644 --- a/src/style/atoms/_typography.scss +++ b/src/style/atoms/_typography.scss @@ -25,6 +25,7 @@ input, .cooldown > span, + .mini-skill, .mini-weaponskill, .mini-language-skill, .attribute.rollable > .name, .attribute.rollable > .wert { font-family: Andalus, sans-serif; diff --git a/src/style/molecules/_sidebar-elements.scss b/src/style/molecules/_sidebar-elements.scss index 62354506..e87381e8 100644 --- a/src/style/molecules/_sidebar-elements.scss +++ b/src/style/molecules/_sidebar-elements.scss @@ -157,6 +157,33 @@ } } + .favourites { + + h3 { + text-align: center; + margin: 8px 0; + } + + .mini-skill, .mini-weaponskill, .mini-language-skill { + background-image: url("/systems/DSA_4-1/assets/velvet_button.png"); + background-repeat: repeat-y; + background-size: cover; + + border: 1px outset #ccc; + + color: white; + border-radius: 4px; + padding: 0 8px; + margin-bottom: 4px; + cursor: pointer; + + &:hover { + text-shadow: 0 0 2px rgba(255, 0, 0, 1); + } + } + + } + .cooldowns { h3 { diff --git a/src/style/organisms/_character-sheet.scss b/src/style/organisms/_character-sheet.scss index 163ef47b..887f0e4e 100644 --- a/src/style/organisms/_character-sheet.scss +++ b/src/style/organisms/_character-sheet.scss @@ -111,9 +111,12 @@ @include liturgies.tab; } + .sidebuttons { + display: none; + } } - &.tiny { + &.tiny:not(.minimized):not(.minimizing) { .header-fields { & > div:not(.attributes) { @@ -151,6 +154,29 @@ section.tab.tab.tab { display: none; } + + .sidebuttons { + position: fixed; + display: block; + margin-left: -136px; + margin-top: 182px; + pointer-events: none; + rotate: 90deg; + + div { + display: flex; + gap: 4px; + + button { + background-image: url("/systems/DSA_4-1/assets/velvet_button.png"); + background-repeat: repeat-y; + background-size: cover; + color: white; + font-weight: bold; + pointer-events: all; + } + } + } } } diff --git a/src/style/organisms/character-tabs/_advsf.scss b/src/style/organisms/character-tabs/_advsf.scss index 7d7834c9..8fc7af3d 100644 --- a/src/style/organisms/character-tabs/_advsf.scss +++ b/src/style/organisms/character-tabs/_advsf.scss @@ -98,3 +98,11 @@ } } + +.dsa41.actor.character.standalone.advsf { + @include tab; + + .advantages-and-specialabilities { + flex-direction: column; + } +} diff --git a/src/style/organisms/character-tabs/_inventory.scss b/src/style/organisms/character-tabs/_inventory.scss index ecb35fb7..d8c96658 100644 --- a/src/style/organisms/character-tabs/_inventory.scss +++ b/src/style/organisms/character-tabs/_inventory.scss @@ -114,3 +114,52 @@ } } } + +.dsa41.sheet.actor.character.standalone.bagpack { + @include tab; + + + .coinage { + position: absolute; + bottom: 0; + right: 8px; + height: 38px; + line-height: 38px; + vertical-align: middle; + } + + .capacity { + position: absolute; + top: 0; + left: 0; + right: 0; + } + + .buttons { + position: absolute; + bottom: 4px; + left: 4px; + + button { + display: inline-block; + } + + } + + .inventory-table { + overflow-x: hidden; + overflow-y: auto; + + position: absolute; + left: 4px; + top: 4px; + right: 4px; + bottom: 38px; + + .equipment { + @include equipment.equipment + } + + } +} + diff --git a/src/style/organisms/character-tabs/_skills.scss b/src/style/organisms/character-tabs/_skills.scss index bbb542d0..e9acdc57 100644 --- a/src/style/organisms/character-tabs/_skills.scss +++ b/src/style/organisms/character-tabs/_skills.scss @@ -45,4 +45,18 @@ } } +} + +.mini-skills { + overflow-x: hidden; + overflow-y: auto; + height: 100%; + @include tab; + + container: unset; + + ul { + list-style-type: none; + padding-left: 0; + } } \ No newline at end of file diff --git a/src/templates/actor/character/main-sheet.hbs b/src/templates/actor/character/main-sheet.hbs index 386fc6b9..8f88ea7c 100644 --- a/src/templates/actor/character/main-sheet.hbs +++ b/src/templates/actor/character/main-sheet.hbs @@ -128,4 +128,17 @@ {{/each}} +
+
+ + + + + {{#if this.hasLiturgies}} + {{/if}} + {{#if this.hasSpells}} + {{/if}} +
+
+
diff --git a/src/templates/actor/character/standalone/advsf.hbs b/src/templates/actor/character/standalone/advsf.hbs new file mode 100644 index 00000000..13434596 --- /dev/null +++ b/src/templates/actor/character/standalone/advsf.hbs @@ -0,0 +1,26 @@ +
+
+

Schlechte Eigenschaften

+
    + {{#each this.flaws}} +
  • {{> "systems/DSA_4-1/templates/ui/partial-advantage-button.hbs" this}}
  • + {{/each}} +
+
+
+

Vor- und Nachteile

+
    + {{#each this.advantages}} +
  • {{> "systems/DSA_4-1/templates/ui/partial-advantage-button.hbs" this}}
  • + {{/each}} +
+
+
+

Sonderfertigkeiten

+
    + {{#each this.specialAbilities}} +
  • {{> "systems/DSA_4-1/templates/ui/partial-sf-button.hbs" this}}
  • + {{/each}} +
+
+
diff --git a/src/templates/actor/character/standalone/bagpack.hbs b/src/templates/actor/character/standalone/bagpack.hbs new file mode 100644 index 00000000..1ab325de --- /dev/null +++ b/src/templates/actor/character/standalone/bagpack.hbs @@ -0,0 +1,20 @@ +
+
+ +
+ +
+ +
+ + +
+ + +
+ + + {{> "systems/DSA_4-1/templates/ui/partial-equipment-button.hbs" equipments}} + +
diff --git a/src/templates/actor/character/standalone/skills.hbs b/src/templates/actor/character/standalone/skills.hbs new file mode 100644 index 00000000..67ff834e --- /dev/null +++ b/src/templates/actor/character/standalone/skills.hbs @@ -0,0 +1,97 @@ +
+
+
+

Kampftalente

+
    + {{#each skills.Kampf}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-weaponskill-button.hbs" this}} +
  • + {{/each}} +
+
+
+
+
+

Körperliche Talente

+
    +
  • + {{#each skills.Körperlich}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
+ +
+
+

Natur Talente

+
    +
  • + {{#each skills.Natur}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
+
+
+

Wissenstalente

+
    +
  • + {{#each skills.Wissen}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
+
+
+

Schriften & Sprachen

+
    +
  • + {{#each skills.Schriften}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-language-button.hbs" this}} +
  • + {{/each}} + {{#each skills.Sprachen}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-language-button.hbs" this}} +
  • + {{/each}} +
+
+
+
+
+

Handwerkliche Talente

+
    +
  • + {{#each skills.Handwerk}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
+
\ No newline at end of file -- 2.43.0 From d355cb2d5cdd6b16d24ae3742bf3f0fd1e45ed1f Mon Sep 17 00:00:00 2001 From: macniel Date: Fri, 14 Nov 2025 21:29:00 +0100 Subject: [PATCH 14/24] fixes orientiation of sidebuttons --- src/style/organisms/_character-sheet.scss | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/style/organisms/_character-sheet.scss b/src/style/organisms/_character-sheet.scss index 887f0e4e..645be5db 100644 --- a/src/style/organisms/_character-sheet.scss +++ b/src/style/organisms/_character-sheet.scss @@ -158,10 +158,11 @@ .sidebuttons { position: fixed; display: block; - margin-left: -136px; - margin-top: 182px; + margin-left: 27px; + margin-top: 48px; pointer-events: none; rotate: 90deg; + transform-origin: top left; div { display: flex; @@ -174,6 +175,9 @@ color: white; font-weight: bold; pointer-events: all; + border-radius: 0; + border-top-left-radius: 8px; + border-top-right-radius: 8px; } } } -- 2.43.0 From 189db593aa7e75cfc1b34aef4fd6ed960e4047c7 Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 16 Nov 2025 10:18:02 +0100 Subject: [PATCH 15/24] fixes styling in merchant sheet --- src/style/atoms/_buttons.scss | 27 +++++++++++++++++++ src/style/atoms/_colours.scss | 8 ++++++ src/style/molecules/_equipment.scss | 3 ++- src/style/molecules/_liturgy-banner.scss | 4 +-- src/style/molecules/_rollable.scss | 13 +++------ src/style/organisms/_group-sheet.scss | 12 ++++----- src/style/organisms/_merchant-sheet.scss | 17 +++++++----- src/templates/actor/merchant/tab-services.hbs | 3 ++- 8 files changed, 62 insertions(+), 25 deletions(-) create mode 100644 src/style/atoms/_buttons.scss diff --git a/src/style/atoms/_buttons.scss b/src/style/atoms/_buttons.scss new file mode 100644 index 00000000..e13fa01d --- /dev/null +++ b/src/style/atoms/_buttons.scss @@ -0,0 +1,27 @@ +@use "./colours"; + +@mixin raised_button { + background: rgba(0, 0, 0, 0.05); + border: 1px solid #ccc; + box-shadow: 1px 1px 1px #ccc; + border-top-right-radius: 8px; + border-bottom-right-radius: 8px; +} + +@mixin uncut_raised_button { + @include raised_button; + border-radius: 8px; + + button { + background: unset; + border: unset; + box-shadow: unset; + color: black; + + &:hover { + color: black; + } + + @include colours.highlight; + } +} \ No newline at end of file diff --git a/src/style/atoms/_colours.scss b/src/style/atoms/_colours.scss index 64689d04..ffad2420 100644 --- a/src/style/atoms/_colours.scss +++ b/src/style/atoms/_colours.scss @@ -83,4 +83,12 @@ $special-action: rgba(68, 34, 204, 0.8); $special-action-color: #000; +@mixin highlight { + &:hover { + text-shadow: 0 0 10px red; + } +} +@mixin svg-highlight { + filter: drop-shadow(0px 0px 10px rgb(255 0 0)); +} \ No newline at end of file diff --git a/src/style/molecules/_equipment.scss b/src/style/molecules/_equipment.scss index 86c606e2..1ff14ae4 100644 --- a/src/style/molecules/_equipment.scss +++ b/src/style/molecules/_equipment.scss @@ -1,4 +1,5 @@ @use "../atoms/assets"; +@use "../atoms/colours" as colour; @mixin equipment($darkmode: false) { position: relative; @@ -44,7 +45,7 @@ &:hover { .name { - text-shadow: 0 0 10px rgb(255 0 0); + @include colour.highlight; } border: 1px solid #ccc; diff --git a/src/style/molecules/_liturgy-banner.scss b/src/style/molecules/_liturgy-banner.scss index 75b73fe7..cb0d4545 100644 --- a/src/style/molecules/_liturgy-banner.scss +++ b/src/style/molecules/_liturgy-banner.scss @@ -221,8 +221,8 @@ $deity_colours_tint: ( } } - .clickable:hover { - text-shadow: 0 0 10px rgb(255 0 0); + .clickable { + @include colour.highlight; } } diff --git a/src/style/molecules/_rollable.scss b/src/style/molecules/_rollable.scss index 69b30a92..ca2d0893 100644 --- a/src/style/molecules/_rollable.scss +++ b/src/style/molecules/_rollable.scss @@ -2,6 +2,7 @@ @use 'sass:map'; @use "../atoms/colours" as colour; @use "../atoms/numbers" as numbers; +@use "../atoms/buttons"; $rollable_colours: ( "nachteil": colour.$nachteil-color, @@ -148,9 +149,7 @@ $rollable_colours_font: ( bottom: 8px; z-index: 3; - &:hover { - text-shadow: 0 0 10px rgb(255 0 0); - } + @include colour.highlight; } } @@ -159,7 +158,7 @@ $rollable_colours_font: ( .die:hover { svg { - filter: drop-shadow(0px 0px 10px rgb(255 0 0)); + @include colour.svg-highlight; } @@ -195,11 +194,7 @@ $rollable_colours_font: ( .container { // background-image: linear-gradient(to right, rgba($color, numbers.$start_gradient), rgba($color, numbers.$end_gradient)); - background: rgba(0, 0, 0, 0.05); - border: 1px solid #ccc; - box-shadow: 1px 1px 1px #ccc; - border-top-right-radius: 8px; - border-bottom-right-radius: 8px; + @include buttons.raised_button; } } } diff --git a/src/style/organisms/_group-sheet.scss b/src/style/organisms/_group-sheet.scss index 00635e88..4d4aa441 100644 --- a/src/style/organisms/_group-sheet.scss +++ b/src/style/organisms/_group-sheet.scss @@ -1,3 +1,5 @@ +@use "../atoms/colours" as colour; + .application.sheet.dsa41.actor.group { .sheet-header { @@ -30,8 +32,8 @@ } } - .rollable:hover { - text-shadow: 0 0 10px rgb(255 0 0); + .rollable { + @include colour.highlight; } .character { @@ -131,9 +133,7 @@ display: inline-block; padding: 0 4px; - &:hover { - text-shadow: 0 0 10px rgb(255 0 0); - } + @include colour.highlight; } } } @@ -168,7 +168,7 @@ &:hover { .item-name { - text-shadow: 0 0 10px rgb(255 0 0); + @include colour.highlight; } } } diff --git a/src/style/organisms/_merchant-sheet.scss b/src/style/organisms/_merchant-sheet.scss index 8325fdf6..1eba2f36 100644 --- a/src/style/organisms/_merchant-sheet.scss +++ b/src/style/organisms/_merchant-sheet.scss @@ -1,3 +1,6 @@ +@use "../atoms/buttons"; + + .dsa41.actor.merchant { .tab.goods.active { @@ -22,9 +25,12 @@ overflow-y: auto; .merchant-good { + @include buttons.uncut_raised_button; + width: 100%; display: grid; break-inside: avoid; + grid-template-columns: 32px 1fr 32px; grid-template-rows: 16px 16px; grid-template-areas: "img title options" "img price options"; @@ -39,6 +45,7 @@ button { grid-area: options; + height: 100%; } .price { @@ -57,12 +64,7 @@ overflow-y: auto; .service { - - border: 1px inset rgba(0, 0, 0, 1); - background-color: rgba(0, 0, 0, 0.2); - border-radius: 4px; - padding: 4px; - margin: 4px 0; + @include buttons.uncut_raised_button; display: grid; grid-template-columns: 32px 1fr 32px; @@ -105,6 +107,9 @@ } &.infinite { + width: 32px; + bottom: -2px; + &::before { content: '∞'; } diff --git a/src/templates/actor/merchant/tab-services.hbs b/src/templates/actor/merchant/tab-services.hbs index 6f69dd1d..ca964624 100644 --- a/src/templates/actor/merchant/tab-services.hbs +++ b/src/templates/actor/merchant/tab-services.hbs @@ -40,7 +40,8 @@ {{this.name}} {{currency this.price}} {{this.availability}} + (lte this.availability 0)}}infinite{{/if}}">{{#unless + (lte this.availability 0)}}{{this.availability}}{{/unless}}
{{/if}} -- 2.43.0 From 46b6ed8f2a5abafb35fda2b261f3a79f84b67683 Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 16 Nov 2025 11:03:50 +0100 Subject: [PATCH 16/24] implements colorful sidebar buttons --- src/module/sheets/characterSheet.mjs | 4 +- src/style/atoms/_buttons.scss | 31 ++++++++ src/style/atoms/_typography.scss | 7 +- src/style/molecules/_sidebar-elements.scss | 71 ++++++++++++------- src/style/organisms/_character-sheet.scss | 3 +- .../organisms/character-tabs/_advsf.scss | 39 ++-------- .../ui/partial-mini-rollable-button.hbs | 2 +- 7 files changed, 93 insertions(+), 64 deletions(-) diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index 91457d1a..329bdf21 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -96,7 +96,8 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { scrollable: ['.inventory'] }, skills: { - template: Skills.template + template: Skills.template, + scrollable: ['.tab.skills'] }, spells: { template: Spells.template @@ -564,6 +565,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { obj.fav = item.getFlag("DSA_4-1", "favourite") obj.id = id + obj.group = item.system.gruppe ?? null if (t) { obj.template = t diff --git a/src/style/atoms/_buttons.scss b/src/style/atoms/_buttons.scss index e13fa01d..270daf15 100644 --- a/src/style/atoms/_buttons.scss +++ b/src/style/atoms/_buttons.scss @@ -24,4 +24,35 @@ @include colours.highlight; } +} + +@mixin pill-button($color:false, $button-color: #F80) { + background-image: url("/systems/DSA_4-1/assets/velvet_button.png"); + background-color: $color; + background-repeat: repeat-y; + background-size: cover; + @if $color { + background-blend-mode: overlay; + } + border-color: $button-color; + border-width: 1px; + border-style: solid; + border-radius: 8px; + box-shadow: 2px 2px 4px #000; + color: $button-color; + cursor: pointer; + display: inline-block; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2); + padding: 0 8px; + height: 28px; + line-height: 28px; + vertical-align: middle; +} + +@mixin mini-button($color:false, $button-color: #F80) { + @include pill-button($color, $button-color); + width: 100%; + border-radius: 2px; + height: 24px; + line-height: 24px; } \ No newline at end of file diff --git a/src/style/atoms/_typography.scss b/src/style/atoms/_typography.scss index ca5c1f46..cdbf65cc 100644 --- a/src/style/atoms/_typography.scss +++ b/src/style/atoms/_typography.scss @@ -25,15 +25,20 @@ input, .cooldown > span, - .mini-skill, .mini-weaponskill, .mini-language-skill, .attribute.rollable > .name, .attribute.rollable > .wert { font-family: Andalus, sans-serif; } + .mini-skill, .mini-weaponskill, .mini-language-skill, .mini-liturgy, .mini-spell, .editor.prosemirror.active, .editor.prosemirror.inactive { font-family: Gentium, sans-serif; } + .mini-skill, .mini-weaponskill, .mini-language-skill, .mini-liturgy, .mini-spell { + font-weight: bold; + text-transform: capitalize; + } + } diff --git a/src/style/molecules/_sidebar-elements.scss b/src/style/molecules/_sidebar-elements.scss index e87381e8..f8a5ba5c 100644 --- a/src/style/molecules/_sidebar-elements.scss +++ b/src/style/molecules/_sidebar-elements.scss @@ -1,5 +1,6 @@ @use "../atoms/colours" as colors; @use "sass:color"; +@use "../atoms/buttons"; .dsa41.sheet.actor.character { @@ -110,9 +111,7 @@ cursor: pointer; } - &:hover { - text-shadow: 0 0 2px rgba(255, 0, 0, 1); - } + @include colors.highlight; } .pa { @@ -124,9 +123,7 @@ cursor: pointer; } - &:hover { - text-shadow: 0 0 2px rgba(255, 0, 0, 1); - } + @include colors.highlight; } .ini { @@ -137,9 +134,7 @@ cursor: pointer; } - &:hover { - text-shadow: 0 0 2px rgba(255, 0, 0, 1); - } + @include colors.highlight; } .tp { @@ -150,10 +145,7 @@ cursor: pointer; } - &:hover { - text-shadow: 0 0 2px rgba(255, 0, 0, 1); - } - + @include colors.highlight; } } @@ -164,22 +156,47 @@ margin: 8px 0; } - .mini-skill, .mini-weaponskill, .mini-language-skill { - background-image: url("/systems/DSA_4-1/assets/velvet_button.png"); - background-repeat: repeat-y; - background-size: cover; - - border: 1px outset #ccc; - - color: white; - border-radius: 4px; - padding: 0 8px; + .mini-skill, .mini-weaponskill, .mini-language-skill, .mini-spell, .mini-liturgy { margin-bottom: 4px; - cursor: pointer; - &:hover { - text-shadow: 0 0 2px rgba(255, 0, 0, 1); - } + + @include colors.highlight; + } + + .mini-skill.Körperlich { + @include buttons.mini-button($color: color.scale(colors.$talent-body-color, $lightness: -50%), $button-color: gold); + } + + .mini-skill.Gesellschaft { + @include buttons.mini-button($color: color.scale(colors.$talent-social-color, $lightness: -50%), $button-color: gold); + } + + .mini-skill.Natur { + @include buttons.mini-button($color: color.scale(colors.$talent-nature-color, $lightness: -50%), $button-color: gold); + } + + .mini-skill.Wissen { + @include buttons.mini-button($color: color.scale(colors.$talent-knowledge-color, $lightness: -50%), $button-color: gold); + } + + .mini-skill.Handwerk { + @include buttons.mini-button($color: color.scale(colors.$talent-crafting-color, $lightness: -50%), $button-color: gold); + } + + .mini-weaponskill { + @include buttons.mini-button($color: color.scale(colors.$kampftalent-color, $lightness: -50%), $button-color: gold); + } + + .mini-language-skill { + @include buttons.mini-button($color: color.scale(colors.$talent-language-color, $lightness: -50%), $button-color: gold); + } + + .mini-spell { + @include buttons.mini-button($color: colors.$zauber-color, $button-color: gold); + } + + .mini-liturgy { + @include buttons.mini-button($color: colors.$liturgie-color, $button-color: gold); } } diff --git a/src/style/organisms/_character-sheet.scss b/src/style/organisms/_character-sheet.scss index 645be5db..52e67a4b 100644 --- a/src/style/organisms/_character-sheet.scss +++ b/src/style/organisms/_character-sheet.scss @@ -9,6 +9,7 @@ @use "./character-tabs/spells"; @use "./character-tabs/liturgies"; @use "./character-tabs/skills"; +@use "../atoms/buttons"; .application.sheet.dsa41.actor.character { @@ -39,7 +40,7 @@ .rkp { .pill { - cursor: pointer; + @include buttons.pill-button; } } diff --git a/src/style/organisms/character-tabs/_advsf.scss b/src/style/organisms/character-tabs/_advsf.scss index 8fc7af3d..26022e6f 100644 --- a/src/style/organisms/character-tabs/_advsf.scss +++ b/src/style/organisms/character-tabs/_advsf.scss @@ -1,3 +1,5 @@ +@use "../../atoms/buttons"; + @mixin tab($darkmode: false) { .advantages-and-specialabilities { @@ -21,19 +23,9 @@ .advantage, .special-ability, .flaw { position: relative; - border: 1px solid gold; - box-shadow: 2px 2px 4px #000; - border-radius: 8px; - height: 24px; - color: gold; - text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2); - display: inline-block; - padding: 0 8px; margin-left: 0; margin-bottom: 4px; - background-image: url("/systems/DSA_4-1/assets/velvet_button.png"); - background-repeat: repeat-y; - background-size: cover; + @include buttons.pill-button($color: rgb(0, 128, 0), $button-color: gold); span { position: relative; @@ -43,20 +35,7 @@ } &.special-ability { - &::after { - background: rgba(128, 0, 96, 0.5); - } - } - - &::after { - content: ""; - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - border-radius: 8px; - background: rgba(0, 128, 0, 0.5); + @include buttons.pill-button($color: rgb(128, 0, 96), $button-color: gold); } & + .advantage, & + .special-ability { @@ -80,18 +59,12 @@ width: 24px; } - &::after { - background: rgba(106, 36, 216, 0.5); - } - + @include buttons.pill-button($color: rgb(106, 36, 216), $button-color: gold); } &.disadvantage { font-style: italic; - - &::after { - background: rgba(128, 0, 0, 0.5); - } + @include buttons.pill-button($color: rgb(128, 0, 0), $button-color: gold); } } } diff --git a/src/templates/ui/partial-mini-rollable-button.hbs b/src/templates/ui/partial-mini-rollable-button.hbs index 7dd171ee..36984790 100644 --- a/src/templates/ui/partial-mini-rollable-button.hbs +++ b/src/templates/ui/partial-mini-rollable-button.hbs @@ -1,3 +1,3 @@ -
+
{{this.name}}
\ No newline at end of file -- 2.43.0 From 692867f2ac70d5784d9a27c6c80699b0ec7e7539 Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 16 Nov 2025 11:41:35 +0100 Subject: [PATCH 17/24] finalises missing sidebutton tabs --- package-lock.json | 8 +- package.json | 2 +- .../sheets/character-standalone/liturgies.mjs | 152 +++++++++++++ .../sheets/character-standalone/spells.mjs | 98 +++++++++ src/module/sheets/characterSheet.mjs | 6 +- .../organisms/character-tabs/_spells.scss | 57 +++++ src/templates/actor/character/main-sheet.hbs | 4 +- .../actor/character/standalone/liturgies.hbs | 204 ++++++++++++++++++ .../actor/character/standalone/spells.hbs | 51 +++++ 9 files changed, 574 insertions(+), 8 deletions(-) create mode 100644 src/module/sheets/character-standalone/liturgies.mjs create mode 100644 src/module/sheets/character-standalone/spells.mjs create mode 100644 src/templates/actor/character/standalone/liturgies.hbs create mode 100644 src/templates/actor/character/standalone/spells.hbs diff --git a/package-lock.json b/package-lock.json index 653f0089..f782fa7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "gulp-json-modify": "^1.0.2" }, "devDependencies": { - "@foundryvtt/foundryvtt-cli": "^3.0.0", + "@foundryvtt/foundryvtt-cli": "^3.0.2", "cb": "^0.1.1", "del": "^8.0.1", "fvtt-types": "npm:@league-of-foundry-developers/foundry-vtt-types@^13.346.0-beta.20250812191140", @@ -209,9 +209,9 @@ } }, "node_modules/@foundryvtt/foundryvtt-cli": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@foundryvtt/foundryvtt-cli/-/foundryvtt-cli-3.0.0.tgz", - "integrity": "sha512-OiF4HtnYg5An1ivVxB68mOj5LO5gMHd4uHmC5nWdD8IYxpK0pSYw3t+cHrUYDp+Tic78uwFuHxLyc+ZNeZXulA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@foundryvtt/foundryvtt-cli/-/foundryvtt-cli-3.0.2.tgz", + "integrity": "sha512-coh4Cf4FD/GHxk2QMsd+3wLMivNeih4rfkbZy8CaYjdlpo6iciFQwxLqznZWtn+5p06zekvS2xLUF55NnbXQDw==", "dev": true, "dependencies": { "chalk": "^5.4.1", diff --git a/package.json b/package.json index 5d99859c..3071030a 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "installToFoundry": "node installToFoundry.mjs" }, "devDependencies": { - "@foundryvtt/foundryvtt-cli": "^3.0.0", + "@foundryvtt/foundryvtt-cli": "^3.0.2", "cb": "^0.1.1", "del": "^8.0.1", "fvtt-types": "npm:@league-of-foundry-developers/foundry-vtt-types@^13.346.0-beta.20250812191140", diff --git a/src/module/sheets/character-standalone/liturgies.mjs b/src/module/sheets/character-standalone/liturgies.mjs new file mode 100644 index 00000000..e88459df --- /dev/null +++ b/src/module/sheets/character-standalone/liturgies.mjs @@ -0,0 +1,152 @@ +import {LiturgyData} from "../../data/miracle/liturgyData.mjs"; + +const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api +const {ActorSheetV2} = foundry.applications.sheets + +export class StandaloneLiturgies extends HandlebarsApplicationMixin(ActorSheetV2) { + + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + position: {width: 520, height: 480}, + classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'liturgies'], + tag: 'form', + actions: { + openEmbeddedDocument: StandaloneLiturgies.#openEmbeddedDocument, + openLiturgyDialog: StandaloneLiturgies.#openLiturgyDialog, + + } + } + + /** @inheritDoc */ + static PARTS = { + form: { + template: `systems/DSA_4-1/templates/actor/character/standalone/liturgies.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 #openLiturgyDialog(event, target) { + this._actor?.sheet.options.actions.openLiturgyDialog.bind(this)(event, target) + } + + _configureRenderOptions(options) { + super._configureRenderOptions(options) + + options.window.title = `${this.document.name}: Segnungen und Liturgien` + + 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 ?? [] + context.liturgies = []; + context.blessings = []; + + actorData.itemTypes.Blessing.forEach((item, index) => { + context.blessings.push({ + deity: item.system.gottheit, + value: item.system.wert + }) + }) + actorData.itemTypes.Liturgy.forEach((item, index) => { + + context.blessings.forEach(({deity, value}) => { + let insertObject = context.liturgies.find(p => p.deity === deity); + if (!insertObject) { + insertObject = { + deity: deity, + lkp: value, + O: [], + I: [], + II: [], + III: [], + IV: [], + V: [], + VI: [], + VII: [], + VIII: [], + "NA": [], + countO: 1, + countI: 1, + countII: 1, + countIII: 1, + countIV: 1, + countV: 1, + countVI: 1, + countVII: 1, + countVIII: 1, + countNA: 0, + total: 3, + + } + context.liturgies.push(insertObject); + } + + // sort by rank + const rankData = LiturgyData.getRankOfLiturgy(item.system, deity) + if (rankData) { + console.log(rankData) + let {index, name, lkp, mod, costKaP} = rankData; + + insertObject["count" + name] = insertObject["count" + name] + 1; + + insertObject[name]?.push({ + id: item._id, + name: item.name, + lkpReq: lkp, + lkpMod: mod, + costKaP, + fav: item.getFlag("DSA_4-1", "favourite"), + rank: index, // get effective liturgy rank based on deity + liturgiekenntnis: deity, + }) + insertObject.total = insertObject.total + 2; + + } + }) + }) + + + // clean up counter + Object.values(context.liturgies).forEach((litObject) => { + + if (litObject.I.length === 0) litObject.countI = false; + if (litObject.II.length === 0) litObject.countII = false; + if (litObject.III.length === 0) litObject.countIII = false; + if (litObject.IV.length === 0) litObject.countIV = false; + if (litObject.V.length === 0) litObject.countV = false; + if (litObject.VI.length === 0) litObject.countVI = false; + if (litObject.VII.length === 0) litObject.countVII = false; + if (litObject.VIII.length === 0) litObject.countVIII = false; + if (litObject.NA.length === 0) litObject.countNA = false; + + + }) + + context.hasLiturgies = context.blessings.length > 0; + + return context + } + + _onRender(context, options) { + } +} \ No newline at end of file diff --git a/src/module/sheets/character-standalone/spells.mjs b/src/module/sheets/character-standalone/spells.mjs new file mode 100644 index 00000000..57b822e8 --- /dev/null +++ b/src/module/sheets/character-standalone/spells.mjs @@ -0,0 +1,98 @@ +const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api +const {ActorSheetV2} = foundry.applications.sheets + +export class StandaloneSpells extends HandlebarsApplicationMixin(ActorSheetV2) { + + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + position: {width: 520, height: 480}, + classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'spells'], + tag: 'form', + actions: { + openEmbeddedDocument: StandaloneSpells.#openEmbeddedDocument, + + } + } + + /** @inheritDoc */ + static PARTS = { + form: { + template: `systems/DSA_4-1/templates/actor/character/standalone/spells.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) + } + + _configureRenderOptions(options) { + super._configureRenderOptions(options) + + options.window.title = `${this.document.name}: Zauber und Rituale` + + return options + } + + async _prepareContext(context, options, object) { + + const actorData = this.document + context.spells = [] + 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 cleanUpMerkmal = (merkmale) => { + return merkmale.split(",").map((merkmal) => merkmal.trim()) + } + + const prepareEigenschaftRoll = (actorData, name) => { + if (name && name !== "*") { + return actorData.system.attribute[name.toLowerCase()].aktuell + } else { + return 0 + } + } + + actorData.itemTypes["Spell"].forEach((item, index) => { + + const eigenschaften = item.system.probe; + const werte = [ + {name: eigenschaften[0], value: prepareEigenschaftRoll(actorData, eigenschaften[0])}, + {name: eigenschaften[1], value: prepareEigenschaftRoll(actorData, eigenschaften[1])}, + {name: eigenschaften[2], value: prepareEigenschaftRoll(actorData, eigenschaften[2])} + ] + context.spells.push({ + id: item._id, + name: item.name, + zfw: item.system.zfw, + hauszauber: item.system.hauszauber, + merkmal: cleanUpMerkmal(item.system.merkmal), + rollEigenschaft1: werte[0].value, + rollEigenschaft2: werte[1].value, + rollEigenschaft3: werte[2].value, + eigenschaft1: werte[0].name, + eigenschaft2: werte[1].name, + eigenschaft3: werte[2].name, + fav: item.getFlag("DSA_4-1", "favourite") + }) + + }) + context.hasSpells = context.spells.length > 0 + + 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 329bdf21..f25d4caf 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -19,6 +19,8 @@ import * as EquipmentDocument from "../documents/equipment.mjs"; import {StandaloneADVSF} from "./character-standalone/advsf.mjs"; 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"; const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api const {ActorSheetV2} = foundry.applications.sheets @@ -62,7 +64,9 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { toggleFav: CharacterSheet.toggleFav, openStandaloneADVSF: CharacterSheet.#openStandaloneADVSF, openStandaloneSkills: CharacterSheet.#openStandaloneSkills, - openBagpack: CharacterSheet.#openBagpack + openBagpack: CharacterSheet.#openBagpack, + openStandaloneSpells: CharacterSheet.#openStandaloneSpells, + openStandaloneLiturgies: CharacterSheet.#openStandaloneLiturgies, } } diff --git a/src/style/organisms/character-tabs/_spells.scss b/src/style/organisms/character-tabs/_spells.scss index 8a47be00..7c27decb 100644 --- a/src/style/organisms/character-tabs/_spells.scss +++ b/src/style/organisms/character-tabs/_spells.scss @@ -87,4 +87,61 @@ padding: 0 4px; } } +} + +.mini-spells { + height: 100%; + display: flex; + flex-direction: column; + + .table-header { + display: grid; + grid-template-columns: 1fr 100px 30px; + padding: 0 8px; + font-weight: bold; + } + + .scrollable-table { + overflow-x: hidden; + overflow-y: auto; + + thead { + display: none; + + } + + + tr { + + td:nth-child(1) { + width: 32px; + } + + td:nth-child(3) { + width: 100px; + } + + td:nth-child(4) { + width: 30px; + } + + .spell.rollable { + position: relative; + + svg { + + position: absolute; + width: 32px; + height: 32px; + z-index: 2; + top: 0; + left: -4px; + + path { + fill: colour.$zauber-color; + } + } + } + } + } } \ No newline at end of file diff --git a/src/templates/actor/character/main-sheet.hbs b/src/templates/actor/character/main-sheet.hbs index 8f88ea7c..611361ed 100644 --- a/src/templates/actor/character/main-sheet.hbs +++ b/src/templates/actor/character/main-sheet.hbs @@ -135,9 +135,9 @@ {{#if this.hasLiturgies}} - {{/if}} + {{/if}} {{#if this.hasSpells}} - {{/if}} + {{/if}}
diff --git a/src/templates/actor/character/standalone/liturgies.hbs b/src/templates/actor/character/standalone/liturgies.hbs new file mode 100644 index 00000000..e8b8cb52 --- /dev/null +++ b/src/templates/actor/character/standalone/liturgies.hbs @@ -0,0 +1,204 @@ +
+
+ +
+ + + von + +
+
+
+ {{#each this.liturgies}} + + + + + + + + + + + + + + {{#each this.O}} + + + + + + {{/each}} + {{#if this.countI}} + + + + {{#each this.I}} + + + + + + {{/each}} + {{/if}} + {{#if this.countII}} + + + + {{#each this.II}} + + + + + {{/each}} + {{/if}} + {{#if this.countIII}} + + + + {{#each this.III}} + + + + + {{/each}} + {{/if}} + {{#if this.countIV}} + + + + {{#each this.IV}} + + + + + {{/each}}{{/if}} + {{#if this.countV}} + + + + {{#each this.V}} + + + + + {{/each}} + {{/if}} + {{#if this.countVI}} + + + + {{#each this.VI}} + + + + + {{/each}} + {{/if}}{{#if this.countVII}} + + + + {{#each this.VII}} + + + + + {{/each}} + {{/if}}{{#if this.countVIII}} + + + + {{#each this.VIII}} + + + + + {{/each}} + {{/if}} + +
Liturgiekenntnis: {{this.lkp}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{/each}} +
\ No newline at end of file diff --git a/src/templates/actor/character/standalone/spells.hbs b/src/templates/actor/character/standalone/spells.hbs new file mode 100644 index 00000000..2ed2e4b5 --- /dev/null +++ b/src/templates/actor/character/standalone/spells.hbs @@ -0,0 +1,51 @@ +
+
+ +
+ + + von + +
+
+ + +
+
+ +
+ + Zaubername + + + Probe + + ZfW +
+
+ + + + + + + + + + + {{#each this.spells}} + + + + + + + {{/each}} + +
ZaubernameProbeZfW
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + + {{this.name}}{{this.eigenschaft1}} {{this.eigenschaft2}} {{this.eigenschaft3}}{{this.zfw}}
+
+ +
\ No newline at end of file -- 2.43.0 From e0e70d126f5b9dfc0abc2029421a80a56014542f Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 16 Nov 2025 11:52:56 +0100 Subject: [PATCH 18/24] fix faulty tab config on creatureSheet --- src/module/sheets/creatureSheet.mjs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/module/sheets/creatureSheet.mjs b/src/module/sheets/creatureSheet.mjs index 87aafffa..895dc9e2 100644 --- a/src/module/sheets/creatureSheet.mjs +++ b/src/module/sheets/creatureSheet.mjs @@ -25,7 +25,6 @@ export class CreatureSheet extends HandlebarsApplicationMixin(ActorSheetV2) { static TABS = { sheet: { tabs: [], - initial: 'meta' } } @@ -66,6 +65,19 @@ export class CreatureSheet extends HandlebarsApplicationMixin(ActorSheetV2) { tabs.tabs.push(tab) } } + + if (!game.user.isGM) { + if (this.document.system.visibility.meta) { + tabs.initial = 'meta' + } else if (this.document.system.visibility.attacks) { + tabs.initial = 'attacks' + } else if (this.document.system.visibility.description) { + tabs.initial = 'description' + } else if (this.document.system.visibility.loot) { + tabs.initial = 'loot' + } + } + return tabs } -- 2.43.0 From 4f4446d327421862d24d368e5be2d4321dbeb425 Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 16 Nov 2025 12:36:19 +0100 Subject: [PATCH 19/24] introduces socketlib as hard requirement enabling players to loot and buy even when they lack the permission to update items they don't own (yet). --- src/main.mjs | 16 +++++++-- src/module/setup/config.mjs | 41 +++++++++++++++++++++++ src/module/sheets/character/equipment.mjs | 2 +- src/module/sheets/characterSheet.mjs | 2 +- src/module/sheets/merchantSheet.mjs | 9 ++--- src/system.json | 12 ++++++- 6 files changed, 70 insertions(+), 12 deletions(-) diff --git a/src/main.mjs b/src/main.mjs index 09d2c24a..f0da9309 100644 --- a/src/main.mjs +++ b/src/main.mjs @@ -2,14 +2,23 @@ import {XmlImportDialog} from "./module/dialog/xmlImportDialog.mjs"; import {initGlobalSettings, initUserSettings} from "./module/settings/global-settings.mjs"; import {setUpActorSheets, setUpItemSheets} from "./module/setup/sheets.mjs"; import {loadPartials} from "./module/setup/partials.mjs"; -import {initCombat, initDataModels, initDocumentClasses, initGlobalAccess} from "./module/setup/config.mjs"; +import { + initSocketLib, + initCombat, + initDataModels, + initDocumentClasses, + initGlobalAccess +} from "./module/setup/config.mjs"; import {initHandlebarHelpers} from "./module/handlebar-helpers/index.mjs"; Hooks.once("init", () => { console.log("DSA 4.1 is ready for development!") - game.DSA41 = initGlobalAccess() + game.DSA41 = { + ...game.DSA41, + ...initGlobalAccess() + } initDocumentClasses(CONFIG) initUserSettings(game.settings) @@ -27,6 +36,9 @@ Hooks.once("init", () => { initHandlebarHelpers(Handlebars) }) +game.DSA41 = {} +initSocketLib(game.DSA41) + Hooks.on("getActorContextOptions", (application, menuItems) => { menuItems.push({ name: "Import from XML", diff --git a/src/module/setup/config.mjs b/src/module/setup/config.mjs index e8778dd1..b603f42e 100644 --- a/src/module/setup/config.mjs +++ b/src/module/setup/config.mjs @@ -73,7 +73,48 @@ function initCombat(config) { } } +function initSocketLib() { + + + Hooks.on("socketlib.ready", () => { + console.log("Socketlib is registering") + let socket = socketlib.registerSystem("DSA_4-1") + socket.register("removeFromLootTable", removeFromLootTable) + socket.register("buyFromLootTable", buyFromLootTable) + if (!game.DSA41) { + game.DSA41 = {} + } + game.DSA41.socket = socket + }) + + + async function removeFromLootTable(actorId, itemId) { + if (actorId && game.actors.get(actorId)) { + const actor = game.actors.get(actorId) + + return await actor.deleteEmbeddedDocuments('Item', [itemId]) + } + } + + async function buyFromLootTable(actorId, itemId) { + if (actorId && game.actors.get(actorId)) { + const actor = game.actors.get(actorId) + const item = actor.items.find(p => p.id === itemId) + if (item.system.quantity != -1) { // -1 means infinite + if (item.system.quantity > 1) { + item.update({'system.quantity': item.system.quantity - 1}) + } else { + actor.deleteEmbeddedDocuments('Item', [item._id]) // delete when the quantity is equal to 0 + } + } + return true + } + } + +} + export { + initSocketLib, initGlobalAccess, initDocumentClasses, initDataModels, diff --git a/src/module/sheets/character/equipment.mjs b/src/module/sheets/character/equipment.mjs index bdb26eaa..8c34b1c8 100644 --- a/src/module/sheets/character/equipment.mjs +++ b/src/module/sheets/character/equipment.mjs @@ -280,7 +280,7 @@ export default { name: "Aus dem Inventar entfernen", icon: '', callback: (target) => { - thisObject.document.deleteEmbeddedDocuments('Item', [target.dataset.itemId]) + game.DSA41.socket.executeAsGM("removeFromLootTable", thisObject.document.id, target.dataset.itemId) }, condition: (target) => { const {itemId} = target.dataset diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index f25d4caf..f99cd01a 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -743,7 +743,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { } else { if (document.parent && document.parent !== this.actor) { - document.parent.items.get(document._id).delete() + game.DSA41.socket.executeAsGM("removeFromLootTable", document.parent.id, document._id) } await this._onDropDocument(event, document) diff --git a/src/module/sheets/merchantSheet.mjs b/src/module/sheets/merchantSheet.mjs index bc9b2b63..2774656f 100644 --- a/src/module/sheets/merchantSheet.mjs +++ b/src/module/sheets/merchantSheet.mjs @@ -109,13 +109,8 @@ export class MerchantSheet extends HandlebarsApplicationMixin(ActorSheetV2) { actor.createEmbeddedDocuments('Item', [item]).then(documents => { documents[0].update({'system.quantity': 1}) }) - if (item.system.quantity != -1) { // -1 means infinite - if (item.system.quantity > 1) { - item.update({'system.quantity': item.system.quantity - 1}) - } else { - this.document.deleteEmbeddedDocuments('Item', [item._id]) // delete when the quantity is equal to 0 - } - } + + game.DSA41.socket.executeAsGM("buyFromLootTable", this.document.id, item.id) ChatMessage.create({ user: game.user._id, speaker: {actor}, diff --git a/src/system.json b/src/system.json index be6b6c09..2c5045b7 100644 --- a/src/system.json +++ b/src/system.json @@ -7,6 +7,7 @@ "minimum": 12, "verified": 13 }, + "dependencies": [], "authors": [ { "name": "GrandpaPoppy" @@ -340,7 +341,16 @@ } } }, - "socket": false, + "socket": true, + "relationships": { + "requires": [ + { + "id": "socketlib", + "type": "module", + "manifest": "https://github.com/farling42/foundryvtt-socketlib/releases/latest/download/module.json" + } + ] + }, "initiative": "1d6", "grid": { "distance": 1, -- 2.43.0 From 6f935644c133842367a7abbf2e2df76cc18efbb1 Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 16 Nov 2025 13:19:54 +0100 Subject: [PATCH 20/24] spell and liturgy dice are now easier to recognise --- src/style/molecules/_liturgy-banner.scss | 8 +++++--- src/style/organisms/character-tabs/_spells.scss | 3 +-- src/templates/actor/character/tab-spells.hbs | 1 + 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/style/molecules/_liturgy-banner.scss b/src/style/molecules/_liturgy-banner.scss index cb0d4545..9e26d6b9 100644 --- a/src/style/molecules/_liturgy-banner.scss +++ b/src/style/molecules/_liturgy-banner.scss @@ -205,11 +205,13 @@ $deity_colours_tint: ( .liturgy.rollable { width: 24px; + padding: 0; svg { - $color: #e4de61; - width: 24px; - height: 24px; + + $color: colour.$liturgie-color; + width: 32px; + height: 32px; top: 1px; z-index: 1; position: relative; diff --git a/src/style/organisms/character-tabs/_spells.scss b/src/style/organisms/character-tabs/_spells.scss index 7c27decb..882f5645 100644 --- a/src/style/organisms/character-tabs/_spells.scss +++ b/src/style/organisms/character-tabs/_spells.scss @@ -27,7 +27,6 @@ z-index: 2; top: 0; left: -4px; - display: none; path { fill: colour.$zauber-color; @@ -59,9 +58,9 @@ border-top-right-radius: 8px; border-bottom-right-radius: 8px; position: absolute; - top: 2px; left: 12px; bottom: 2px; + height: 2px; right: 33%; z-index: 0; pointer-events: none; diff --git a/src/templates/actor/character/tab-spells.hbs b/src/templates/actor/character/tab-spells.hbs index 1b6e8a1e..42ca511e 100644 --- a/src/templates/actor/character/tab-spells.hbs +++ b/src/templates/actor/character/tab-spells.hbs @@ -25,6 +25,7 @@ Probe ZfW Merkmale + -- 2.43.0 From eca965e434050edbb2dc0c8dc0f22724276189fc Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 16 Nov 2025 13:26:02 +0100 Subject: [PATCH 21/24] increases discoverability of die interactions --- src/style/atoms/_colours.scss | 2 ++ src/style/molecules/_liturgy-banner.scss | 5 ++++- src/style/organisms/character-tabs/_spells.scss | 7 +++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/style/atoms/_colours.scss b/src/style/atoms/_colours.scss index ffad2420..774e4429 100644 --- a/src/style/atoms/_colours.scss +++ b/src/style/atoms/_colours.scss @@ -87,8 +87,10 @@ $special-action-color: #000; &:hover { text-shadow: 0 0 10px red; } + cursor: pointer; } @mixin svg-highlight { filter: drop-shadow(0px 0px 10px rgb(255 0 0)); + cursor: pointer; } \ No newline at end of file diff --git a/src/style/molecules/_liturgy-banner.scss b/src/style/molecules/_liturgy-banner.scss index 9e26d6b9..affcde17 100644 --- a/src/style/molecules/_liturgy-banner.scss +++ b/src/style/molecules/_liturgy-banner.scss @@ -216,11 +216,14 @@ $deity_colours_tint: ( z-index: 1; position: relative; - path { fill: $color; } } + + &:hover { + @include colour.svg-highlight; + } } .clickable { diff --git a/src/style/organisms/character-tabs/_spells.scss b/src/style/organisms/character-tabs/_spells.scss index 882f5645..93c98bc6 100644 --- a/src/style/organisms/character-tabs/_spells.scss +++ b/src/style/organisms/character-tabs/_spells.scss @@ -32,6 +32,11 @@ fill: colour.$zauber-color; } } + + &:hover { + @include colour.svg-highlight; + } + } @@ -43,6 +48,8 @@ span { position: relative; z-index: 1; + + @include colour.highlight; } } -- 2.43.0 From c00a6b11b7c83b8cbe0264b2a58819747809c251 Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 16 Nov 2025 13:35:39 +0100 Subject: [PATCH 22/24] fixes NPE as ranged items could be equipped when the actor doesnt even have the skill to do so. --- src/module/sheets/characterSheet.mjs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index f99cd01a..59320a07 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -479,17 +479,19 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { if (fernkampf) { const fkitems = fernkampf.system.rangedSkills.map((skillInQuestion) => actorData.items.find(p => p.name === skillInQuestion)) - fkitems.forEach(skill => { - context.attacks.push({ - name: skill.name, - id: fernkampf._id, - skillId: skill._id, - using: fernkampf.name, - isRanged: true, - at: `${this.document.system.fk.aktuell + skill.system.at}`, - tp: `${fernkampf.system.rangedAttackDamage}`, - ini: `${context.inidice}w6 + ${context.inivalue + fernkampf.system.iniModifier ?? 0}`, - }) + fkitems?.forEach(skill => { + if (skill) { + context.attacks.push({ + name: skill.name, + id: fernkampf._id, + skillId: skill._id, + using: fernkampf.name, + isRanged: true, + at: `${this.document.system.fk.aktuell + skill.system.at}`, + tp: `${fernkampf.system.rangedAttackDamage}`, + ini: `${context.inidice}w6 + ${context.inivalue + fernkampf.system.iniModifier ?? 0}`, + }) + } }) } if (links) { @@ -500,7 +502,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { meitems.push(item) } }) - meitems.forEach(skill => { + meitems?.forEach(skill => { const obj = skill context.attacks.push({ name: obj.name, @@ -523,7 +525,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { meitems.push(item) } }) - meitems.forEach(skill => { + meitems?.forEach(skill => { const obj = skill context.attacks.push({ name: obj.name, -- 2.43.0 From 182aeb2dc6a051c93383040626482b717a2b677a Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 16 Nov 2025 16:07:42 +0100 Subject: [PATCH 23/24] implements optional fatigue system. --- src/module/data/character.mjs | 4 ++ src/module/documents/character.mjs | 17 ++++++- src/module/settings/global-settings.mjs | 12 +++++ src/module/sheets/character/health.mjs | 18 ++++++++ src/module/sheets/characterSheet.mjs | 14 +++--- .../organisms/character-tabs/_health.scss | 46 ++++++++++++++----- src/templates/actor/character/tab-health.hbs | 45 ++++++++++++------ 7 files changed, 122 insertions(+), 34 deletions(-) diff --git a/src/module/data/character.mjs b/src/module/data/character.mjs index 8297bd7d..c571c246 100644 --- a/src/module/data/character.mjs +++ b/src/module/data/character.mjs @@ -138,6 +138,10 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { key: new StringField(), notiz: new StringField(), })), + erschoepfung: new SchemaField({ // only with DSA_4-1.optional_erschoepfung + max: new NumberField({required: true, integer: true}), + aktuell: new NumberField({required: true, integer: true}), + }), wunden: new SchemaField({ aktuell: new NumberField({required: true, integer: true}), // only with DSA_4-1.optional_trefferzonen = false max: new NumberField({required: true, integer: true}), // only with DSA_4-1.optional_trefferzonen = false diff --git a/src/module/documents/character.mjs b/src/module/documents/character.mjs index f158a631..bf116fee 100644 --- a/src/module/documents/character.mjs +++ b/src/module/documents/character.mjs @@ -105,6 +105,19 @@ export class Character extends Actor { systemData.ausweichen.basis = systemData.pa.basis systemData.ausweichen.aktuell = systemData.ausweichen.basis + systemData.ueberanstrengung = 0 + + if (game.settings.get("DSA_4-1", "optional_erschoepfung")) { + + systemData.erschoepfung = { + aktuell: systemData.erschoepfung.aktuell ?? 0, + max: ko + } + if (systemData.erschoepfung.aktuell > systemData.erschoepfung.max) { + systemData.ueberanstrengung = systemData.erschoepfung.aktuell - systemData.erschoepfung.max + } + } + if (game.settings.get("DSA_4-1", "optional_ruestungzonen")) { systemData.rs = { @@ -119,11 +132,11 @@ export class Character extends Actor { } else { systemData.rs = 0; // only with DSA_4-1.optional_trefferzonen = false } - systemData.be = 0; + systemData.be = 0 + systemData.ueberanstrengung; // half KO is the maximum a character can sustain wounds before collapsing - systemData.wunden.max = ko / 2; + systemData.wunden.max = Math.round(ko / 2); if (game.settings.get("DSA_4-1", "optional_trefferzonen")) { systemData.wunden.kopf = 0 systemData.wunden.brust = 0 diff --git a/src/module/settings/global-settings.mjs b/src/module/settings/global-settings.mjs index 50d919a8..65777bb8 100644 --- a/src/module/settings/global-settings.mjs +++ b/src/module/settings/global-settings.mjs @@ -36,6 +36,18 @@ function initGlobalSettings(settings) { requiresReload: true }) + settings.register('DSA_4-1', 'optional_erschoepfung', { + name: "Optional: Erschöpfung", + hint: "Aktiviert Regeln für das Spiel mit Erschöpfung und Überanstregung", + scope: "world", + config: true, + type: Boolean, + default: false, + onChange: value => { + }, + requiresReload: true + }) + settings.register('DSA_4-1', 'optional_distanzklassen', { name: "Optional: Distanzklassen", hint: "Aktiviert Regeln für das Spiel mit Distanzklassen", diff --git a/src/module/sheets/character/health.mjs b/src/module/sheets/character/health.mjs index 0e409976..9c3de352 100644 --- a/src/module/sheets/character/health.mjs +++ b/src/module/sheets/character/health.mjs @@ -27,6 +27,24 @@ export default { 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] diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index 59320a07..73e94338 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -67,6 +67,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { openBagpack: CharacterSheet.#openBagpack, openStandaloneSpells: CharacterSheet.#openStandaloneSpells, openStandaloneLiturgies: CharacterSheet.#openStandaloneLiturgies, + setWounds: CharacterSheet.#setWounds, } } @@ -320,6 +321,12 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { new StandaloneLiturgies(this.document) } + static async #setWounds(event, target) { + const {value} = target.dataset + this.document.update({"system.wunden.aktuell": value}) + this.render(true) + } + _configureRenderOptions(options) { super._configureRenderOptions(options) @@ -445,13 +452,6 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { context.img = actorData.img context.effects = actorData.effects ?? [] - context.maxWounds = actorData.system.wunden.max ?? 3 - context.wounds = actorData.system.wunden.gesamt ?? 0 - context.woundsFilled = [] - for (let i = 1; i <= context.maxWounds; i++) { - context.woundsFilled[i] = i <= context.wounds - } - 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") diff --git a/src/style/organisms/character-tabs/_health.scss b/src/style/organisms/character-tabs/_health.scss index 1e3163b7..a8fb173d 100644 --- a/src/style/organisms/character-tabs/_health.scss +++ b/src/style/organisms/character-tabs/_health.scss @@ -3,8 +3,8 @@ display: grid; grid-template-columns: 1fr 320px; - grid-template-rows: 32px 32px 1fr; - grid-template-areas: "res res" "wounds wounds" "actions actions" "cooldowns cooldowns"; + grid-template-rows: 32px 32px 32px 1fr; + grid-template-areas: "res res" "wounds wounds" "fatigue fatigue" "effects effects" "effects effects"; padding: 8px; gap: 8px; @@ -31,7 +31,7 @@ } - .wounds { + .wounds, .fatigue { position: relative; height: 24px; display: flex; @@ -90,22 +90,46 @@ } - .actions { - grid-area: actions; - padding: 0; + .fatigue { + grid-area: fatigue; + flex-direction: row; - .grid-of-actions { - display: unset; + label { + span { + display: inline-block; + height: 26px; + line-height: 26px; + vertical-align: middle; + } + + input { + position: absolute; + right: 0; + height: 26px; + text-align: center; + padding: 0; + margin: 0; + width: 28px; + } } + + .filled-segment { + background-color: rgba(0, 128, 0, 0.8); + + &.danger { + background-color: rgba(255, 0, 0, 0.8); + } + } + } - .cooldowns { - grid-area: cooldowns; + .effects { + grid-area: effects; } &.zones { - grid-template-areas: "res res" "wounds wounds" "actions paperdoll" "cooldowns paperdoll"; + grid-template-areas: "res res" "wounds wounds" "fatigue fatigue" "effects paperdoll" "effects paperdoll"; .paperdoll { grid-area: paperdoll; diff --git a/src/templates/actor/character/tab-health.hbs b/src/templates/actor/character/tab-health.hbs index 2d49e510..dab36be2 100644 --- a/src/templates/actor/character/tab-health.hbs +++ b/src/templates/actor/character/tab-health.hbs @@ -42,31 +42,48 @@
{{#if (not trefferzonen)}}
- + {{#each this.woundsFilled}} {{#if this}} -
{{@index}}
{{else}} -
{{@index}}
+
{{@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}} -
+
    {{#each effects}} -- 2.43.0 From 02f0ecc9dd5b6e3763d71d6db91abb5fdad31c40 Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 16 Nov 2025 16:56:54 +0100 Subject: [PATCH 24/24] 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}} +
    -- 2.43.0