Adds Group Management
parent
41045cb482
commit
691a811275
15
src/main.mjs
15
src/main.mjs
|
|
@ -7,6 +7,8 @@ import { VornachteileDataModel } from "./module/data/vornachteile.mjs";
|
||||||
import { Character } from "./module/documents/character.mjs";
|
import { Character } from "./module/documents/character.mjs";
|
||||||
import { CharacterSheet } from "./module/sheets/characterSheet.mjs";
|
import { CharacterSheet } from "./module/sheets/characterSheet.mjs";
|
||||||
import { VornachteilSheet } from "./module/sheets/vornachteilSheet.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() {
|
async function preloadHandlebarsTemplates() {
|
||||||
return loadTemplates([
|
return loadTemplates([
|
||||||
|
|
@ -31,6 +33,7 @@ Hooks.once("init", () => {
|
||||||
// Configure System Data Models.
|
// Configure System Data Models.
|
||||||
CONFIG.Actor.dataModels = {
|
CONFIG.Actor.dataModels = {
|
||||||
character: PlayerCharacterDataModel,
|
character: PlayerCharacterDataModel,
|
||||||
|
group: GroupDataModel
|
||||||
};
|
};
|
||||||
|
|
||||||
CONFIG.Item.dataModels = {
|
CONFIG.Item.dataModels = {
|
||||||
|
|
@ -51,6 +54,11 @@ Hooks.once("init", () => {
|
||||||
makeDefault: true,
|
makeDefault: true,
|
||||||
label: 'DSA41.CharacterLabels.Item'
|
label: 'DSA41.CharacterLabels.Item'
|
||||||
})
|
})
|
||||||
|
Actors.registerSheet('dsa41.group', GroupSheet, {
|
||||||
|
types: ["group"],
|
||||||
|
makeDefault: true,
|
||||||
|
label : 'DSA41.GroupLabel.Item'
|
||||||
|
})
|
||||||
|
|
||||||
// Register sheet application classes
|
// Register sheet application classes
|
||||||
Items.registerSheet('dsa41.skill', SkillSheet, {
|
Items.registerSheet('dsa41.skill', SkillSheet, {
|
||||||
|
|
@ -69,11 +77,16 @@ Hooks.once("init", () => {
|
||||||
label: 'DSA41.VornachteilLabels.Item'
|
label: 'DSA41.VornachteilLabels.Item'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
return preloadHandlebarsTemplates();
|
return preloadHandlebarsTemplates();
|
||||||
})
|
})
|
||||||
|
|
||||||
Hooks.on('dropActorSheetData', (actor, sheet, data) => {
|
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() {
|
Hooks.once("ready", async function() {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
export class Group extends Actor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
prepareData() {
|
||||||
|
|
||||||
|
console.log("prepare", this);
|
||||||
|
super.prepareData();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,13 +2,14 @@
|
||||||
@use "./colours";
|
@use "./colours";
|
||||||
@use "./assets";
|
@use "./assets";
|
||||||
|
|
||||||
.dsa41.sheet.actor.character {
|
.dsa41.sheet.actor {
|
||||||
|
|
||||||
nav.sheet-tabs.tabs {
|
nav.sheet-tabs.tabs {
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flow;
|
display: flow;
|
||||||
border-top: unset;
|
border-top: unset;
|
||||||
|
border-bottom: unset;
|
||||||
|
|
||||||
a.item[data-tab] {
|
a.item[data-tab] {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,6 @@
|
||||||
@use "_attributes";
|
@use "_attributes";
|
||||||
@use "_sidebar-elements";
|
@use "_sidebar-elements";
|
||||||
@use "_character-sheet";
|
@use "_character-sheet";
|
||||||
|
@use "_group-sheet";
|
||||||
@use "_tabs";
|
@use "_tabs";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,9 @@
|
||||||
],
|
],
|
||||||
"documentTypes": {
|
"documentTypes": {
|
||||||
"Actor": {
|
"Actor": {
|
||||||
|
"group": {
|
||||||
|
|
||||||
|
},
|
||||||
"character": {
|
"character": {
|
||||||
"numberFields": [
|
"numberFields": [
|
||||||
"groesse", "alter", "gewicht"
|
"groesse", "alter", "gewicht"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
<form class="{{cssClass}} {{actor.type}} flexcol" autocomplete="off">
|
||||||
|
|
||||||
|
{{!-- Sheet Header --}}
|
||||||
|
<header class="sheet-header">
|
||||||
|
|
||||||
|
<input class="sheet-name" type="text" name="actor.name" value="{{actor.name}}" />
|
||||||
|
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{{!-- Sheet Tab Navigation --}}
|
||||||
|
<nav class="sheet-tabs tabs" data-group="primary">
|
||||||
|
<a class="item" data-tab="characters">Charaktere</a>
|
||||||
|
<a class="item" data-tab="inventory">Inventar</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{{!-- Sheet Body --}}
|
||||||
|
<section class="sheet-body">
|
||||||
|
<div class="tab characters" data-group="primary" data-tab="characters">
|
||||||
|
<div class="characters-overview">
|
||||||
|
{{#each characters}}
|
||||||
|
<div class="character">
|
||||||
|
<div class="header">
|
||||||
|
<img class="profile-img" src="{{this.img}}" style="object-fit: cover;" title="{{this.name}}" alt="{{this.name}}"/>
|
||||||
|
<span class="name">{{this.name}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="mini-attributes">
|
||||||
|
{{#each this.attributes}}
|
||||||
|
<div class="mini-attribute">
|
||||||
|
<span class="value">{{this.value}}</span>
|
||||||
|
<span class="name">{{this.name}}</span>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
<div class="fixedElements">
|
||||||
|
<ul class="inline-list">
|
||||||
|
{{#each skills}}<li class="mini-skill clickable" data-id="{{this.id}}">{{this.name}}: {{this.taw}}</li>{{/each}}
|
||||||
|
</ul>
|
||||||
|
<ul class="inline-list">
|
||||||
|
{{#each advantages}}<li class="mini-advantage clickable" data-id="{{this.id}}">{{this.name}} {{#if this.value}}[{{this.value}}]{{/if}}</li>{{/each}}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{{#if this.isOwner}}
|
||||||
|
<div class="owneroptions">
|
||||||
|
<button>Leave Group</button>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tab inventory" data-group="primary" data-tab="inventory">
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</form>
|
||||||
Loading…
Reference in New Issue