From 099d1c5d165b6c93d0c379f1c34a836231001714 Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 12 Oct 2025 10:49:37 +0200 Subject: [PATCH 1/3] tableized group sheet --- src/module/sheets/groupSheet.mjs | 64 +++++++++++++++++-------- src/templates/actor/group-sheet.hbs | 74 ++++++++++++++++------------- 2 files changed, 85 insertions(+), 53 deletions(-) diff --git a/src/module/sheets/groupSheet.mjs b/src/module/sheets/groupSheet.mjs index 6536d933..fafc86a7 100644 --- a/src/module/sheets/groupSheet.mjs +++ b/src/module/sheets/groupSheet.mjs @@ -28,13 +28,18 @@ export class GroupSheet extends ActorSheet { // update group - const settings = {...group.system.settings} + let settings = {...group.system.settings} character.items.filter((i) => i.type === "Advantage").forEach((advantage) => { - settings[this.#stringToKeyFieldName(advantage.name)] = false + if (!settings[sheet.#stringToKeyFieldName(advantage.name)]) { + settings[sheet.#stringToKeyFieldName(advantage.name)] = false + } }) character.items.filter((i) => i.type === "Skill").forEach((skill) => { - settings[this.#stringToKeyFieldName(skill.name)] = false - }), + if (!settings[sheet.#stringToKeyFieldName(skill.name)]) { + settings[sheet.#stringToKeyFieldName(skill.name)] = false + } + }) + await group.update({ system: { characters: [ @@ -55,7 +60,7 @@ export class GroupSheet extends ActorSheet { } #stringToKeyFieldName(s) { - return s.replace(/[ \[\]:]/g, "_").toLowerCase() + return s } /** @override */ @@ -74,14 +79,46 @@ export class GroupSheet extends ActorSheet { context.system = groupData.system; context.flags = groupData.flags; context.characters = [] + context.isGM = game.user.isGM; context.fields = []; const hiddenFields = Object.entries(groupData.system.settings).filter(([key, value]) => value === true).map(([key, value]) => key) + context.fields = {} + context.fields["head"] = {} + for (const field of hiddenFields) { + + context.fields[field] = {} + + for (const characterId of groupData.system.characters) { + const character = await game.actors.get(characterId) + context.fields[field][character.name] = "-" + + } + } + + for (const characterId of groupData.system.characters) { const character = await game.actors.get(characterId) - context.characters.push( + + character.items.filter((i) => i.type === "Advantage").filter((i) => hiddenFields.includes(this.#stringToKeyFieldName(i.name))).map((advantage) => { + const n = this.#stringToKeyFieldName(advantage.name) + if (!context.fields[n]) { + context.fields[n] = {} + } + context.fields[n][character.name] = advantage.system.value ?? "Ja" // TODO: Allow GM roll + }) + + character.items.filter((i) => i.type === "Skill").filter((i) => hiddenFields.includes(this.#stringToKeyFieldName(i.name))).map((skill) => { + const n = this.#stringToKeyFieldName(skill.name) + if (!context.fields[n]) { + context.fields[n] = {} + } + context.fields[n][character.name] = skill.system.taw ?? 0 // TODO: Allow GM roll + }) + + context.fields.head[character.name] = { img: character.img, name: character.name, @@ -96,25 +133,10 @@ export class GroupSheet extends ActorSheet { {name: "KO", value: character.system.attribute.ko.aktuell}, {name: "KK", value: character.system.attribute.kk.aktuell}, ], - advantages: character.items.filter((i) => i.type === "Advantage").filter((i) => hiddenFields.includes(this.#stringToKeyFieldName(i.name))).map((advantage) => { - return { - name: advantage.name, - id: advantage._id, - value: advantage.system.value, - } - }), - skills: character.items.filter((i) => i.type === "Skill").filter((i) => hiddenFields.includes(this.#stringToKeyFieldName(i.name))).map((skill) => { - return { - name: skill.name, - taw: skill.system.taw, - id: skill._id - } - }), isLimited: character.isOwner || !character.limited, isVisible: character.isOwner || character.visible, isOwner: character.isOwner } - ) } context.equipments = []; diff --git a/src/templates/actor/group-sheet.hbs b/src/templates/actor/group-sheet.hbs index 52327def..65d7ce0d 100644 --- a/src/templates/actor/group-sheet.hbs +++ b/src/templates/actor/group-sheet.hbs @@ -17,7 +17,7 @@ {{!-- Sheet Body --}}
- {{#if actor.limited}} + {{#unless isGM}}
{{#each characters}} {{#if this.isVisible}} @@ -33,14 +33,19 @@
{{else}}
- {{#each characters}} - {{#if this.isVisible}} -
-
- {{this.name}} - {{this.name}} -
+ + + + + {{#each this.fields.head}} + + {{/each}} + + + + {{#each this.fields}} + {{#unless (eq @key "head")}} + + + + {{#each this}} + + {{/each}} + + + {{/unless}} + {{/each}} + +
Charakter +
+
+ {{this.name}} + {{this.name}} +
{{#if this.isLimited}}
{{#each this.attributes}} @@ -51,32 +56,37 @@
{{/each}}
-
-
    - {{#each skills}} -
  • {{this.name}}: {{this.taw}}
  • {{/each}} -
-
    - {{#each advantages}} -
  • {{this.name}} {{#if this.value}} - [{{this.value}}]{{/if}}
  • {{/each}} -
-
{{/if}} - {{#if this.isOwner}} -
-
- {{/if}} - - {{/if}} - {{/each}} +
+ {{ @key}} + + {{#if (eq this "-")}} + + {{else}} + {{this}} + {{/if}} +
- {{/if}} + {{/unless}}
{{> 'systems/DSA_4-1/templates/ui/partial-equipment-group-button.hbs' equipments}} From 5db955c25011cb7ddd2dfb2488abc68df018df6b Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 12 Oct 2025 14:52:53 +0200 Subject: [PATCH 2/3] skills on group sheet can now be rolled on with GM Roll per default --- src/module/sheets/characterSheet.mjs | 2 - src/module/sheets/groupSheet.mjs | 92 +++++++++++++++++++- src/style/_group-sheet.scss | 4 + src/templates/actor/group-sheet.hbs | 21 ++++- src/templates/ui/partial-rollable-button.hbs | 2 +- 5 files changed, 112 insertions(+), 9 deletions(-) diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index 7cdef543..690260d8 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -524,8 +524,6 @@ export class CharacterSheet extends ActorSheet { rollMode: game.settings.get('core', 'rollMode'), }) } - - } } diff --git a/src/module/sheets/groupSheet.mjs b/src/module/sheets/groupSheet.mjs index fafc86a7..cf5b2010 100644 --- a/src/module/sheets/groupSheet.mjs +++ b/src/module/sheets/groupSheet.mjs @@ -83,7 +83,10 @@ export class GroupSheet extends ActorSheet { context.fields = []; - const hiddenFields = Object.entries(groupData.system.settings).filter(([key, value]) => value === true).map(([key, value]) => key) + const hiddenFields = Object.entries(groupData.system.settings) + .sort(([key, value], [otherKey, otherValue]) => key.localeCompare(otherKey)) + .filter(([key, value]) => value === true) + .map(([key, value]) => key) context.fields = {} context.fields["head"] = {} @@ -98,7 +101,6 @@ export class GroupSheet extends ActorSheet { } } - for (const characterId of groupData.system.characters) { const character = await game.actors.get(characterId) @@ -115,7 +117,19 @@ export class GroupSheet extends ActorSheet { if (!context.fields[n]) { context.fields[n] = {} } - context.fields[n][character.name] = skill.system.taw ?? 0 // TODO: Allow GM roll + const eigenschaften = Object.values(skill.system.probe); + context.fields[n][character.name] = { + taw: skill.system.taw, + eigenschaft1: eigenschaften[0], + eigenschaft2: eigenschaften[1], + eigenschaft3: eigenschaften[2], + rollEigenschaft1: character.system.attribute[eigenschaften[0].toLowerCase()].aktuell, + rollEigenschaft2: character.system.attribute[eigenschaften[1].toLowerCase()].aktuell, + rollEigenschaft3: character.system.attribute[eigenschaften[2].toLowerCase()].aktuell, + name: skill.name, + actor: character._id, + } + ?? 0 // TODO: Allow GM roll }) context.fields.head[character.name] = @@ -153,6 +167,9 @@ export class GroupSheet extends ActorSheet { } }) + context.settings = Object.fromEntries(Object.entries(groupData.system.settings) + .sort(([key, value], [otherKey, otherValue]) => key.localeCompare(otherKey))) + return await context; } @@ -160,6 +177,70 @@ export class GroupSheet extends ActorSheet { this.object.items.get(documentId).sheet.render(true) } + + _evaluateRoll(rolledDice, { + taw, + lowerThreshold = 1, + upperThreshold = 20, + countToMeisterlich = 3, + countToPatzer = 3, + werte = [] + }) { + let tap = taw; + let meisterlichCounter = 0; + let patzerCounter = 0; + let failCounter = 0; + + rolledDice.forEach((rolledDie, index) => { + if (tap < 0 && rolledDie.result > werte[index]) { + tap -= rolledDie.result - werte[index]; + if (tap < 0) { // konnte nicht vollständig ausgeglichen werden + failCounter++; + } + } else if (rolledDie.result > werte[index]) { // taw ist bereits aufgebraucht und wert kann nicht ausgeglichen werden + tap -= rolledDie.result - werte[index]; + failCounter++; + } + if (rolledDie.result <= lowerThreshold) meisterlichCounter++; + if (rolledDie.result > upperThreshold) patzerCounter++; + }) + + return { + tap, + meisterlich: meisterlichCounter === countToMeisterlich, + patzer: patzerCounter === countToPatzer, + } + } + + async _onTalentRoll(event) { + event.preventDefault(); + const dataset = event.currentTarget.dataset; + const actor = await game.actors.get(dataset.actorId); + console.log(dataset, actor) + if (dataset.rolleigenschaft1) { + let roll1 = new Roll("3d20", actor.getRollData()); + + let evaluated1 = (await roll1.evaluate()) + + const dsaDieRollEvaluated = this._evaluateRoll(evaluated1.terms[0].results, { + taw: dataset.taw, + werte: [dataset.rolleigenschaft1, dataset.rolleigenschaft2, dataset.rolleigenschaft3], + }) + + if (dsaDieRollEvaluated.tap >= 0) { // erfolg + evaluated1.toMessage({ + speaker: ChatMessage.getSpeaker({actor: actor}), + flavor: ` ${dsaDieRollEvaluated.meisterlich ? 'Meisterlich geschafft' : 'Geschafft'} mit ${dsaDieRollEvaluated.tap} Punkten übrig`, + }, {rollMode: "gmroll"}) + } else { // misserfolg + evaluated1.toMessage({ + speaker: ChatMessage.getSpeaker({actor: actor}), + flavor: ` ${dsaDieRollEvaluated.meisterlich ? 'Gepatzt' : ''} mit ${Math.abs(dsaDieRollEvaluated.tap)} Punkten daneben`, + }, {rollMode: "gmroll"}) + } + } + } + activateListeners(html) { super.activateListeners(html); @@ -190,6 +271,11 @@ export class GroupSheet extends ActorSheet { evt.stopPropagation(); }) + html.on('click', ".rollable", (evt) => { + this._onTalentRoll(evt) + evt.stopPropagation() + }) + new ContextMenu(html, '.equipment', [ { name: "Aus dem Gruppeninventar entfernen", diff --git a/src/style/_group-sheet.scss b/src/style/_group-sheet.scss index 5316d214..0f61f602 100644 --- a/src/style/_group-sheet.scss +++ b/src/style/_group-sheet.scss @@ -56,6 +56,10 @@ } } + .rollable:hover { + text-shadow: 0 0 10px rgb(255 0 0); + } + .character { width: 192px; diff --git a/src/templates/actor/group-sheet.hbs b/src/templates/actor/group-sheet.hbs index 65d7ce0d..776e34e7 100644 --- a/src/templates/actor/group-sheet.hbs +++ b/src/templates/actor/group-sheet.hbs @@ -36,7 +36,7 @@ - + {{#each this.fields.head}}
Charakter
@@ -75,7 +75,22 @@ {{#if (eq this "-")}} {{else}} - {{this}} + {{#if this.taw}} +
+ {{this.taw}} ({{this.eigenschaft1}}, {{this.eigenschaft2}} + , {{this.eigenschaft3}}) +
+ {{else}} + Ja + {{/if}} {{/if}} {{/each}} @@ -93,7 +108,7 @@
{{#if owner}}
- {{#each actor.system.settings}} + {{#each settings}}
diff --git a/src/templates/ui/partial-rollable-button.hbs b/src/templates/ui/partial-rollable-button.hbs index 1d4c1390..50ecbef6 100644 --- a/src/templates/ui/partial-rollable-button.hbs +++ b/src/templates/ui/partial-rollable-button.hbs @@ -1,6 +1,6 @@
From 912a8dde88138280b736be4cf1b18014680593ac Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 12 Oct 2025 14:53:17 +0200 Subject: [PATCH 3/3] removes todo marker --- src/module/sheets/groupSheet.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module/sheets/groupSheet.mjs b/src/module/sheets/groupSheet.mjs index cf5b2010..7e179037 100644 --- a/src/module/sheets/groupSheet.mjs +++ b/src/module/sheets/groupSheet.mjs @@ -129,7 +129,7 @@ export class GroupSheet extends ActorSheet { name: skill.name, actor: character._id, } - ?? 0 // TODO: Allow GM roll + ?? 0 }) context.fields.head[character.name] =