Compare commits

..

No commits in common. "f74bb38f3a8a5b46fecf6ac32436aab2e79e19f5" and "e14e4e71081a64c338abd0b31f8f70ee17a5602c" have entirely different histories.

8 changed files with 149 additions and 202 deletions

View File

@ -901,33 +901,33 @@ export class CharacterSheet extends foundry.appv1.sheets.ActorSheet {
evt.stopPropagation(); evt.stopPropagation();
} }
}) })
/*
html.on('dragstart', '.equipment', (evt) => { html.on('dragstart', '.equipment', (evt) => {
evt.originalEvent.dataTransfer.setData("application/json", JSON.stringify({ evt.originalEvent.dataTransfer.setData("application/json", JSON.stringify({
documentId: evt.currentTarget.dataset.id documentId: evt.currentTarget.dataset.id
})); }));
})*/ })
/*
html.on('drop', '.equipped', async (evt) => { html.on('drop', '.equipped', async (evt) => {
const {actor, target, setId} = evt.currentTarget.dataset; const {actor, target, setId} = evt.currentTarget.dataset;
try { try {
const {documentId} = JSON.parse(evt.originalEvent.dataTransfer.getData("application/json")); const {documentId} = JSON.parse(evt.originalEvent.dataTransfer.getData("application/json"));
if (actor === this.object._id && documentId) { // managing equipped items if (actor === this.object._id && documentId) { // managing equipped items
//const slot = this.#isWorn(documentId, setId) //const slot = this.#isWorn(documentId, setId)
//const updateObject = await this.#getEquipmentset(Number(setId)) //const updateObject = await this.#getEquipmentset(Number(setId))
const updateObject = this.#mapAllSets() const updateObject = this.#mapAllSets()
updateObject[`system.heldenausruestung.${setId}.${target}`] = documentId; updateObject[`system.heldenausruestung.${setId}.${target}`] = documentId;
console.log(updateObject); console.log(updateObject);
await this.object.update(updateObject); await this.object.update(updateObject);
} }
evt.stopPropagation(); evt.stopPropagation();
} catch (e) { } catch (e) {
} }
})*/ })
new foundry.applications.ux.ContextMenu(html[0], '.talent.rollable', [ new foundry.applications.ux.ContextMenu(html[0], '.talent.rollable', [
{ {

View File

@ -1,6 +1,5 @@
const {HandlebarsApplicationMixin} = foundry.applications.api const {HandlebarsApplicationMixin} = foundry.applications.api
const {ActorSheetV2} = foundry.applications.sheets const {ActorSheetV2} = foundry.applications.sheets
const {ContextMenu} = foundry.applications.ux
export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) { export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
@ -9,22 +8,17 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
position: {width: 520, height: 480}, position: {width: 520, height: 480},
classes: ['dsa41', 'sheet', 'actor', 'group'], classes: ['dsa41', 'sheet', 'actor', 'group'],
tag: 'form', tag: 'form',
dragDrop: [{
dropSelector: '.tab.inventory.active'
}],
form: { form: {
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false,
handler: GroupSheet.#onSubmitForm handler: GroupSheet.#onSubmitForm
}, },
window: {
resizable: true,
},
actions: { actions: {
roll: GroupSheet.#dieRoll, roll: GroupSheet.#dieRoll,
editImage: ActorSheetV2.DEFAULT_OPTIONS.actions.editImage, editImage: ActorSheetV2.DEFAULT_OPTIONS.actions.editImage,
openEmbeddedDocument: GroupSheet.#openEmbeddedDocument, openEmbeddedDocument: GroupSheet.#openEmbeddedDocument,
openActorDocument: GroupSheet.#openActorDocument, openActorDocument: GroupSheet.#openActorDocument,
removeFromParty: GroupSheet.#removeFromParty,
} }
} }
@ -33,6 +27,7 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
tabs: [ tabs: [
{id: 'members', group: 'sheet', label: 'Gruppenmitglieder'}, {id: 'members', group: 'sheet', label: 'Gruppenmitglieder'},
{id: 'inventory', group: 'sheet', label: 'Gruppeninventar'}, {id: 'inventory', group: 'sheet', label: 'Gruppeninventar'},
// settings is only added on context
], ],
initial: 'members' initial: 'members'
} }
@ -49,45 +44,51 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
inventory: { inventory: {
template: `systems/DSA_4-1/templates/actor/group/tab-inventory.hbs` template: `systems/DSA_4-1/templates/actor/group/tab-inventory.hbs`
}, },
settings: {
template: `systems/DSA_4-1/templates/actor/group/tab-settings.hbs`
}
} }
constructor(options = {}) {
super(options);
}
/** static async onDroppedData(group, sheet, data) {
* Handle form submission if (data.type === "Actor") {
* @this {AdvantageSheet} const uuid = await foundry.utils.parseUuid(data.uuid);
* @param {SubmitEvent} event const character = await (game.actors.get(uuid.id))
* @param {HTMLFormElement} form
* @param {FormDataExtended} formData
*/
static async #onSubmitForm(event, form, formData) {
event.preventDefault()
if (formData.object.name) { // check if character already is part of the group
await (game.folders.get(this.document.system.groupId)).update({name: formData.object.name}) if (group.system.characters.includes(character._id)) {
} ui.notifications.warn(`${character.name} befindet sich bereits in der Heldengruppe ${group.name}`)
return false;
await this.document.update(formData.object) // Note: formData.object
}
#createDragDropHandlers() {
return this.options.dragDrop.map((d) => {
d.permissions = {
dragstart: this._canDragStart.bind(this),
drop: this._canDragDrop.bind(this)
} }
d.callbacks = {
dragstart: this._onDragStart.bind(this),
dragover: this._onDragOver.bind(this), // update group
drop: this._onDrop.bind(this) let settings = {...group.system.settings}
} character.items.filter((i) => i.type === "Advantage").forEach((advantage) => {
return new DragDrop(d) if (!settings[sheet.#stringToKeyFieldName(advantage.name)]) {
}) settings[sheet.#stringToKeyFieldName(advantage.name)] = false
}
})
character.items.filter((i) => i.type === "Skill").forEach((skill) => {
if (!settings[sheet.#stringToKeyFieldName(skill.name)]) {
settings[sheet.#stringToKeyFieldName(skill.name)] = false
}
})
await group.update({
system: {
characters: [
...group.system.characters,
character._id
],
settings: settings
}
})
ui.notifications.info(`${character.name} ist der Heldengruppe ${group.name} beigetreten`)
}
if (data.type === "Equipment") {
const uuid = await foundry.utils.parseUuid(data.uuid);
const equipment = await (game.actors.get(uuid.id))
ui.notifications.info(`${equipment.name} befindet sich nun im Inventar der Heldengruppe ${group.name}`)
return true;
}
} }
#stringToKeyFieldName(s) { #stringToKeyFieldName(s) {
@ -109,47 +110,43 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
console.log(evt) console.log(evt)
} }
async #onUpdateCharacterSettings(data) { static async #removeFromParty(evt) {
if (data.type === "character") { const dataset = evt.srcElement.dataset;
const group = this.document;
const charactersWithoutMember = group.system.characters.filter(id => id !== dataset.id)
group.update({
system: {
characters: charactersWithoutMember
}
})
// update group
let settings = {...this.document.system.settings}
data.items.filter((i) => i.type === "Advantage").forEach((advantage) => {
if (!settings[this.#stringToKeyFieldName(advantage.name)]) {
settings[this.#stringToKeyFieldName(advantage.name)] = false
}
})
data.items.filter((i) => i.type === "Skill").forEach((skill) => {
if (!settings[this.#stringToKeyFieldName(skill.name)]) {
settings[this.#stringToKeyFieldName(skill.name)] = false
}
})
await this.document.update({"system.settings": settings})
}
} }
_getTabsConfig(group) { /**
const tabs = foundry.utils.deepClone(super._getTabsConfig(group)) * Handle form submission
* @this {AdvantageSheet}
* @param {SubmitEvent} event
* @param {HTMLFormElement} form
* @param {FormDataExtended} formData
*/
static async #onSubmitForm(event, form, formData) {
event.preventDefault()
// Modify tabs based on document properties await this.document.update(formData.object) // Note: formData.object
if (game.user.isGM) {
tabs.tabs.push({id: "settings", group: "sheet", label: "Einstellungen"})
}
return tabs
} }
/** @override */ /** @override */
async _prepareContext(options) { async _prepareContext(options) {
const context = await super._prepareContext(options) const context = await super._prepareContext(options)
const groupData = context.document
context.system = groupData.system // Use a safe clone of the actor data for further operations.
context.flags = groupData.flags const groupData = context.document;
// Add the actor's data to context.data for easier access, as well as flags.
context.system = groupData.system;
context.flags = groupData.flags;
context.characters = [] context.characters = []
context.isGM = game.user.isGM context.isGM = game.user.isGM;
context.name = groupData.name
context.img = groupData.img
context.fields = []; context.fields = [];
@ -190,8 +187,15 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
if (!context.fields[n]) { if (!context.fields[n]) {
context.fields[n] = {} context.fields[n] = {}
} }
const eigenschaften = Object.values(skill.system.probe);
context.fields[n][character.name] = { context.fields[n][character.name] = {
taw: skill.system.taw ?? "0", 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, name: skill.name,
actor: character._id, actor: character._id,
} }
@ -219,11 +223,11 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
} }
} }
context.inventoryItems = []; context.equipments = [];
const actorData = context.document; const actorData = context.document;
actorData.items.forEach((item, index) => { Object.values(actorData.items).forEach((item, index) => {
if (item.type === "Equipment") { if (item.type === "Equipment") {
context.inventoryItems.push({ context.equipments.push({
index: index, index: index,
id: item._id, id: item._id,
quantity: item.system.quantity, quantity: item.system.quantity,
@ -240,7 +244,7 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
} }
_onRender(context, options) { _onRender(context, options) {
/*ContextMenu.implementation.create(this, this.element, ".equipment", [ new ContextMenu(this.element, ".equipment", [
{ {
name: "Aus dem Gruppeninventar entfernen", name: "Aus dem Gruppeninventar entfernen",
icon: '<i class="fa-solid fa-trash"></i>', icon: '<i class="fa-solid fa-trash"></i>',
@ -251,83 +255,7 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
} }
], { ], {
jQuery: false jQuery: false
});*/
// Drag-drop
new foundry.applications.ux.DragDrop.implementation({
dragSelector: ".inventory-table .equipment",
dropSelector: ".inventory-table",
permissions: {
dragstart: this._canDragStart.bind(this),
drop: this._canDragDrop.bind(this)
},
callbacks: {
dragstart: this._onDragStart.bind(this),
drop: this._onDrop.bind(this)
}
}).bind(this.element);
// Update Group Members when either an Actor was moved into the linked Folder or removed from the linked Folder
Hooks.on('updateActor', (data) => {
if (data._id !== this.document._id) { // dont update yourself when you update yourself... baka!
if (data.type === "character" && data.folder?._id === this.document.system.groupId) {
this.#onUpdateCharacterSettings(data)
this.render()
} else if (data.type === "character") {
this.render()
}
}
}); });
}
/**
* An event that occurs when a drag workflow begins for a draggable item on the sheet.
* @param {DragEvent} event The initiating drag start event
* @returns {Promise<void>}
* @protected
*/
async _onDragStart(event) {
const target = event.currentTarget;
if ("link" in event.target.dataset) return;
let dragData;
// Owned Items
if (target.dataset.itemId) {
const item = this.actor.items.get(target.dataset.itemId);
dragData = item.toDragData();
}
// Active Effect
if (target.dataset.effectId) {
const effect = this.actor.effects.get(target.dataset.effectId);
dragData = effect.toDragData();
}
// Set data transfer
if (!dragData) return;
event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
}
// TODO needs to be fixed once Character Sheet is migrated to ActorSheetV2
async _onDrop(event) {
const data = TextEditor.implementation.getDragEventData(event);
const actor = this.actor;
const allowed = Hooks.call("dropActorSheetData", actor, this, data);
if (allowed === false) return;
// Dropped Documents
const documentClass = foundry.utils.getDocumentClass(data.type);
if (documentClass) {
const document = await documentClass.fromDropData(data);
await this._onDropDocument(event, document);
// No duplication by moving items from one actor to another
if (document.parent) {
document.parent.items.get(document._id).delete()
}
await this._onDropDocument(event, document);
}
} }
} }

View File

@ -1,14 +1,40 @@
.application.sheet.dsa41.actor.group { .dsa41.sheet.actor.group {
.window-content {
display: unset;
position: relative;
}
.sheet-header { .sheet-header {
.sheet-name {
font-size: 24pt;
height: 48px;
}
display: grid; }
grid-template-columns: 32px 1fr;
gap: 8px;
img { .sheet-tabs {
height: 32px; position: absolute;
width: 32px; left: 0;
right: 0;
top: 76px;
height: 32px;
padding: 0 16px;
}
.sheet-body {
position: absolute;
top: 98px;
left: 0;
bottom: 0;
right: 0;
padding: 8px;
margin: 8px;
div.tab {
height: 100%;
position: relative;
} }
} }

View File

@ -1,8 +1,6 @@
<div> <div>
<header class="sheet-header"> <header class="sheet-header">
<img class="img" src="{{img}}" data-action="editImage" data-edit="img" alt="{{name}}"
title="{{name}}"/>
<input class="sheet-name" type="text" name="name" value="{{name}}"/> <input class="sheet-name" type="text" name="name" value="{{name}}"/>
</header> </header>

View File

@ -14,7 +14,7 @@
<tbody> <tbody>
{{#each inventoryItems}} {{#each inventoryItems}}
<tr class="equipment" data-item-id="{{this.id}}" draggable="true"> <tr class="equipment" data-id="{{this.id}}" draggable="true">
<td class="icon"><img alt="" src="{{this.icon}}" width="16" height="16"></td> <td class="icon"><img alt="" src="{{this.icon}}" width="16" height="16"></td>
<td class="name">{{this.name}}</td> <td class="name">{{this.name}}</td>
<td class="quantity">{{this.quantity}}</td> <td class="quantity">{{this.quantity}}</td>

View File

@ -59,11 +59,18 @@
{{#if (eq this "-")}} {{#if (eq this "-")}}
{{else}} {{else}}
{{#if (lt this.taw 0)}} {{#if this.taw}}
<div class="rollable" data-actor-id="{{this.actor}}" <div class="rollable" data-actor-id="{{this.actor}}"
data-taw="{{this.taw}}" data-taw="{{this.taw}}"
data-name="{{this.name}}"> data-name="{{this.name}}"
{{this.taw}} data-eigenschaft1="{{this.eigenschaft1}}"
data-eigenschaft2="{{this.eigenschaft2}}"
data-eigenschaft3="{{this.eigenschaft3}}"
data-rollEigenschaft1="{{this.rollEigenschaft1}}"
data-rollEigenschaft2="{{this.rollEigenschaft2}}"
data-rollEigenschaft3="{{this.rollEigenschaft3}}">
{{this.taw}} ({{this.eigenschaft1}}, {{this.eigenschaft2}}
, {{this.eigenschaft3}})
</div> </div>
{{else}} {{else}}
Ja Ja

View File

@ -1,12 +0,0 @@
<section class="tab {{tabs.settings.id}} {{tabs.settings.cssClass}}"
data-tab="{{tabs.settings.id}}"
data-group="{{tabs.settings.group}}">
<ul>
{{#each system.settings}}
<div>
<label><input name="system.settings.{{@key}}" type="checkbox" {{checked this}}> {{@key}}</label>
</div>
{{/each}}
</ul>
</section>

View File

@ -11,7 +11,7 @@
{{#each this}} {{#each this}}
<tr class="equipment" data-item-id="{{this.id}}" draggable="true"> <tr class="equipment" data-id="{{this.id}}" draggable="true">
<td class="icon"><img alt="" src="{{this.icon}}" width="16" height="16"></td> <td class="icon"><img alt="" src="{{this.icon}}" width="16" height="16"></td>
<td class="name">{{this.name}}</td> <td class="name">{{this.name}}</td>
<td class="quantity">{{this.quantity}}</td> <td class="quantity">{{this.quantity}}</td>