From 691a8112751ecd0ff2119232d10102f149f3ae45 Mon Sep 17 00:00:00 2001 From: macniel Date: Fri, 3 Oct 2025 11:03:34 +0200 Subject: [PATCH] Adds Group Management --- src/main.mjs | 15 ++- src/module/data/group.mjs | 20 ++++ src/module/documents/group.mjs | 12 +++ src/module/sheets/groupSheet.mjs | 90 ++++++++++++++++ src/style/_group-sheet.scss | 160 ++++++++++++++++++++++++++++ src/style/_tabs.scss | 5 +- src/style/styles.scss | 2 + src/system.json | 5 +- src/templates/actor/group-sheet.hbs | 55 ++++++++++ 9 files changed, 360 insertions(+), 4 deletions(-) create mode 100644 src/module/data/group.mjs create mode 100644 src/module/documents/group.mjs create mode 100644 src/module/sheets/groupSheet.mjs create mode 100644 src/style/_group-sheet.scss create mode 100644 src/templates/actor/group-sheet.hbs diff --git a/src/main.mjs b/src/main.mjs index 1992fa77..22e9aef3 100644 --- a/src/main.mjs +++ b/src/main.mjs @@ -7,6 +7,8 @@ import { VornachteileDataModel } from "./module/data/vornachteile.mjs"; import { Character } from "./module/documents/character.mjs"; import { CharacterSheet } from "./module/sheets/characterSheet.mjs"; import { VornachteilSheet } from "./module/sheets/vornachteilSheet.mjs"; +import {GroupDataModel} from "./module/data/group.mjs"; +import {GroupSheet} from "./module/sheets/groupSheet.mjs"; async function preloadHandlebarsTemplates() { return loadTemplates([ @@ -31,6 +33,7 @@ Hooks.once("init", () => { // Configure System Data Models. CONFIG.Actor.dataModels = { character: PlayerCharacterDataModel, + group: GroupDataModel }; CONFIG.Item.dataModels = { @@ -51,6 +54,11 @@ Hooks.once("init", () => { makeDefault: true, label: 'DSA41.CharacterLabels.Item' }) + Actors.registerSheet('dsa41.group', GroupSheet, { + types: ["group"], + makeDefault: true, + label : 'DSA41.GroupLabel.Item' + }) // Register sheet application classes Items.registerSheet('dsa41.skill', SkillSheet, { @@ -69,11 +77,16 @@ Hooks.once("init", () => { label: 'DSA41.VornachteilLabels.Item' }) + return preloadHandlebarsTemplates(); }) Hooks.on('dropActorSheetData', (actor, sheet, data) => { - return CharacterSheet.onDroppedData(actor, sheet, data); + if (actor.type === "character") { + return CharacterSheet.onDroppedData(actor, sheet, data); + } else { + return GroupSheet.onDroppedData(actor, sheet, data); + } } ) Hooks.once("ready", async function() { diff --git a/src/module/data/group.mjs b/src/module/data/group.mjs new file mode 100644 index 00000000..8bcbf8af --- /dev/null +++ b/src/module/data/group.mjs @@ -0,0 +1,20 @@ +const { + SchemaField, NumberField, StringField, EmbeddedDocumentField, DocumentIdField, ArrayField, ForeignDocumentField +} = foundry.data.fields; + +export class GroupDataModel extends foundry.abstract.TypeDataModel { + + static defineSchema() { + return { + name: new StringField(), + inventory: new SchemaField({ + quantity: new NumberField(), + item: new DocumentIdField(Item) + }), + characters: new ArrayField( + new DocumentIdField(Actor) + ) + } + } + +} diff --git a/src/module/documents/group.mjs b/src/module/documents/group.mjs new file mode 100644 index 00000000..837b6a23 --- /dev/null +++ b/src/module/documents/group.mjs @@ -0,0 +1,12 @@ +export class Group extends Actor { + + /** + * @override + */ + prepareData() { + + console.log("prepare", this); + super.prepareData(); + } + +} diff --git a/src/module/sheets/groupSheet.mjs b/src/module/sheets/groupSheet.mjs new file mode 100644 index 00000000..5d77b33a --- /dev/null +++ b/src/module/sheets/groupSheet.mjs @@ -0,0 +1,90 @@ +export class GroupSheet extends ActorSheet { + /**@override */ + static get defaultOptions() { + return foundry.utils.mergeObject(super.defaultOptions, { + classes: ['dsa41', 'sheet', 'actor', 'group'], + width: 520, + height: 480, + tabs: [ + { + navSelector: '.sheet-tabs', + contentSelector: '.sheet-body', + initial: 'description', + }, + ], + }); + } + + /** @override */ + async getData() { + const context = super.getData(); + + // Use a safe clone of the actor data for further operations. + const skillData = context.data; + + // Add the actor's data to context.data for easier access, as well as flags. + context.system = skillData.system; + context.flags = skillData.flags; + + context.characters = []; + + for (const characterId of skillData.system.characters) { + const character = await game.actors.get(characterId) + context.characters.push( + { + img: character.img, + name: character.name, + attributes: [ + { name: "MU", value: character.system.attribute.mu.aktuell }, + { name: "KL", value: character.system.attribute.kl.aktuell }, + { name: "IN", value: character.system.attribute.in.aktuell }, + { name: "CH", value: character.system.attribute.ch.aktuell }, + { name: "FF", value: character.system.attribute.ff.aktuell }, + { name: "GE", value: character.system.attribute.ge.aktuell }, + { name: "KO", value: character.system.attribute.ko.aktuell }, + { name: "KK", value: character.system.attribute.kk.aktuell }, + ], + advantages: character.items.filter( (i) => i.type === "Advantage").map( (advantage) => { + return { + name: advantage.name, + id: advantage._id, + value: advantage.system.value, + } + }), + skills: character.items.filter( (i) => i.type === "Skill").map( (skill) => { + return { + name: skill.name, + taw: skill.system.taw, + id: skill._id + } + }), + isOwner: character.isOwner + } + ) + } + console.log(context.characters) + return await context; + + } + + /** @override */ + get template() { + return `systems/DSA_4-1/templates/actor/group-sheet.hbs`; + } + + static async onDroppedData(group, sheet, data) { + if (data.type === "Actor") { + const uuid = await foundry.utils.parseUuid(data.uuid); + const character = await (game.actors.get(uuid.id)) + await group.update({ + system: { + characters: [ + ...group.system.characters, + character._id + ] + } + }) + ui.notifications.info(`${character.name} ist der Heldengruppe ${group.name} beigetreten`) + } + } +} diff --git a/src/style/_group-sheet.scss b/src/style/_group-sheet.scss new file mode 100644 index 00000000..5101d62c --- /dev/null +++ b/src/style/_group-sheet.scss @@ -0,0 +1,160 @@ +.dsa41.sheet.actor.group { + + + .window-content { + display: unset; + position: relative; + } + + .sheet-header { + .sheet-name { + font-size: 24pt; + height: 48px; + } + + } + + .sheet-tabs { + position: absolute; + left: 0; + right: 0; + top: 27px; + height: 32px; + } + + .sheet-body { + position: absolute; + top: 112px; + left: 2px; + bottom: 2px; + right: 2px; + + div.tab { + height: 100%; + position: relative; + } + } + + .characters-overview { + + display: inline-flex; + overflow-x: auto; + height: 100%; + width: 100%; + + .character { + + width: 192px; + position: relative; + + .header { + + position: relative; + height: 80px; + overflow: hidden; + left: 0; + right: 0; + + img { + position: absolute; + top: 0; + height: 80px; + width: 100%; + left: 0; + right: 0; + + &::before { + + } + } + + span.name { + position: absolute; + bottom: 0; + left: 0; + right: 0; + text-align: center; + background-color: rgba(0, 0, 0, 0.5); + color: white; + } + + } + + .mini-attributes { + + display: grid; + height: 24px; + grid-template-columns: repeat(8, 1fr); + + .mini-attribute { + + border-left: 1px solid black; + position: relative; + width: 24px; + + &:first-of-type { + border-left: 0; + } + + .value { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + line-height: 100%; + vertical-align: middle; + text-align: center; + display: block; + } + + .name { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 14px; + text-align: center; + display: block; + } + + } + + } + + .fixedElements { + position: absolute; + overflow: scroll; + top: 102px; + bottom: 20px; + left: 0; + right: 0; + + .inline-list { + list-style: none; + padding: 0; + display: block; + + .mini-skill, .mini-advantage { + display: inline-block; + padding: 0 4px; + &:hover { + text-shadow: 0 0 10px rgb(255 0 0); + } + } + } + } + + .owneroptions { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 36px; + } + + } + + } + +} diff --git a/src/style/_tabs.scss b/src/style/_tabs.scss index 10fd0d37..d2e66b98 100644 --- a/src/style/_tabs.scss +++ b/src/style/_tabs.scss @@ -2,13 +2,14 @@ @use "./colours"; @use "./assets"; -.dsa41.sheet.actor.character { +.dsa41.sheet.actor { nav.sheet-tabs.tabs { position: relative; display: flow; border-top: unset; + border-bottom: unset; a.item[data-tab] { @@ -43,4 +44,4 @@ } -} \ No newline at end of file +} diff --git a/src/style/styles.scss b/src/style/styles.scss index f6b2c084..9df419d2 100644 --- a/src/style/styles.scss +++ b/src/style/styles.scss @@ -3,4 +3,6 @@ @use "_attributes"; @use "_sidebar-elements"; @use "_character-sheet"; +@use "_group-sheet"; @use "_tabs"; + diff --git a/src/system.json b/src/system.json index 61cfad8a..1a6511c7 100644 --- a/src/system.json +++ b/src/system.json @@ -81,6 +81,9 @@ ], "documentTypes": { "Actor": { + "group": { + + }, "character": { "numberFields": [ "groesse", "alter", "gewicht" @@ -193,4 +196,4 @@ "url": "https://git.macniel.online/macniel/foundry-dsa41-game", "manifest": "https://git.macniel.online/macniel/foundry-dsa41-game/releases/download/{{VERSION}}/system.json", "download": "https://git.macniel.online/macniel/foundry-dsa41-game/releases/download/{{VERSION}}/release.zip" -} \ No newline at end of file +} diff --git a/src/templates/actor/group-sheet.hbs b/src/templates/actor/group-sheet.hbs new file mode 100644 index 00000000..69bbe95a --- /dev/null +++ b/src/templates/actor/group-sheet.hbs @@ -0,0 +1,55 @@ +
+ + {{!-- Sheet Header --}} +
+ + + +
+ + {{!-- Sheet Tab Navigation --}} + + + {{!-- Sheet Body --}} +
+
+
+ {{#each characters}} +
+
+ {{this.name}} + {{this.name}} +
+
+ {{#each this.attributes}} +
+ {{this.value}} + {{this.name}} +
+ {{/each}} +
+
+
    + {{#each skills}}
  • {{this.name}}: {{this.taw}}
  • {{/each}} +
+
    + {{#each advantages}}
  • {{this.name}} {{#if this.value}}[{{this.value}}]{{/if}}
  • {{/each}} +
+
+ {{#if this.isOwner}} +
+ +
+ {{/if}} +
+ {{/each}} +
+
+
+
+
+ +