Compare commits

...

2 Commits

Author SHA1 Message Date
macniel 1afdd483e6 Character Creation with Default Values is no longer possible (got to be but its not scope of MVP anyway).
Skills either from Compendia or Imported Entries can now be uniquely added to a Character.

This approach will help us later with adding other Elements like Advantages (these need a "uniqueness" Attribute), Spells (always unique), Miracles (also always unique), Equipment
2025-10-02 16:52:56 +02:00
macniel 32031eb548 When a character is created, its base-skills are now added from compendium and added to the actor as an embedded document. 2025-10-01 22:27:21 +02:00
12 changed files with 362 additions and 396 deletions

View File

@ -7,7 +7,6 @@ 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 {DragDropDSA41} from "./module/extensions/DragDropDSA41.mjs";
async function preloadHandlebarsTemplates() {
return loadTemplates([
@ -21,6 +20,10 @@ async function preloadHandlebarsTemplates() {
Hooks.once("init", () => {
game.DSA41 = {
rollItemMacro
}
// Configure custom Document implementations.
CONFIG.Actor.documentClass = Character;
@ -35,7 +38,10 @@ Hooks.once("init", () => {
Advantage: VornachteileDataModel
}
CONFIG.ux.DragDrop = DragDropDSA41;
CONFIG.Combat.initiative = {
formula: `1d6 + @attribute.ini`,
decimals: 0
}
console.log("DSA 4.1 is ready for development!")
@ -66,5 +72,44 @@ Hooks.once("init", () => {
})
Hooks.on('dropActorSheetData', (actor, sheet, data) => {
CharacterSheet.onDroppedData(actor, sheet, data);
return CharacterSheet.onDroppedData(actor, sheet, data);
} )
Hooks.once("ready", async function() {
// Wait to register hotbar drop hook on ready so that modules could register earlier if they want to
Hooks.on("hotbarDrop", (bar, data, slot) => createBoilerplateMacro(data, slot));
});
async function createBoilerplateMacro(data, slot) {
console.log(data, slot)
if (data.type !== "Item") return;
if (!("data" in data)) return ui.notifications.warn("You can only create macro buttons for owned Items");
const item = data.data;
// Create the macro command
const command = `game.DSA41.rollItemMacro("${item.name}");`;
let macro = game.macros.entities.find(m => (m.name === item.name) && (m.command === command));
if (!macro) {
macro = await Macro.create({
name: item.name,
type: "script",
img: item.img,
command: command,
flags: { "dsa41.itemMacro": true }
});
}
game.user.assignHotbarMacro(macro, slot);
return false;
}
function rollItemMacro(itemName) {
const speaker = ChatMessage.getSpeaker();
let actor;
if (speaker.token) actor = game.actors.tokens[speaker.token];
if (!actor) actor = game.actors.get(speaker.actor);
const item = actor ? actor.items.find(i => i.name === itemName) : null;
if (!item) return ui.notifications.warn(`Your controlled Actor does not have an item named ${itemName}`);
// Trigger the item roll
return item.roll();
}

View File

@ -1,5 +1,8 @@
import {Skill} from "../documents/skill.mjs";
import {SkillDataModel} from "./skill.mjs";
const {
SchemaField, NumberField, StringField, ArrayField, ForeignDocumentField
SchemaField, NumberField, StringField, EmbeddedDocumentField, DocumentIdField, ArrayField, ForeignDocumentField
} = foundry.data.fields;
export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel {
@ -103,7 +106,7 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel {
gilde: new StringField(),
}),
vornachteile: new ArrayField(new SchemaField({
vornachteil: new ForeignDocumentField(Item),
vornachteil: new DocumentIdField(Item),
wert: new NumberField({ required: false, integer: true }),
})),
sonderfertigkeiten: new ArrayField(new SchemaField({
@ -111,13 +114,9 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel {
auswahlen: new ArrayField(new StringField()),
})),
talente: new ArrayField(new SchemaField({
talent: new ForeignDocumentField(Item),
taw: new NumberField({integer: true, required: true}),
})
),
talente: new ArrayField(new DocumentIdField(Item)),
zauber: new ArrayField(new SchemaField({
talent: new ForeignDocumentField(Item),
talent: new DocumentIdField(),
zfw: new NumberField({integer: true, required: true}),
})),
liturgien: new ArrayField(new SchemaField({
@ -140,78 +139,6 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel {
}
async _onCreate(data, options, userId) {
// prepare base talents
const talentsByName = [
"Athletik", "Klettern", "Körperbeherrschung", "Schleichen", "Schwimmen", "Selbstbeherrschung", "Sich Verstecken", "Singen", "Sinnenschärfe", "Tanzen", "Zechen",
"Menschenkenntnis", "Überreden",
"Fährtensuchen", "Orientierung", "Wildnisleben",
"Götter/Kulte", "Rechnen", "Sagen/Legenden",
"Heilkunde: Wunden", "Holzbearbeitung", "Kochen", "Lederverarbeitung", "Malen/Zeichnen", "Schneidern"
]
const talente = []
talentsByName.forEach( talentName => {
const talent = game.items.getName(talentName);
console.log(talent);
if (talent) {
talente.push({
taw: 0,
talent
})
} else {
console.error(`${talentName} not found in items`)
}
})
// push base talents
await game.actors.getName(data.name).update({system: {talente}})
const startEigenschaften = {
"mu": {
start: 10,
aktuell: 10,
mod: 0
},
"kl": {
start: 10,
aktuell: 10,
mod: 0
},
"in": {
start: 10,
aktuell: 10,
mod: 0
},
"ch": {
start: 10,
aktuell: 10,
mod: 0
},
"ff": {
start: 10,
aktuell: 10,
mod: 0
},
"ge": {
start: 10,
aktuell: 10,
mod: 0
},
"ko": {
start: 10,
aktuell: 10,
mod: 0
},
"kk": {
start: 10,
aktuell: 10,
mod: 0
}
}
await game.actors.getName(data.name).update({system: {attribute: startEigenschaften}})
super._onCreate(data, options, userId);
}

View File

@ -8,6 +8,7 @@ export class SkillDataModel extends BaseItem {
return {
name: new StringField({ required: true }),
gruppe: new StringField({ required: true }),
taw: new NumberField({ integer: true, initial: 0 }),
probe: new ArrayField(new StringField(), { exact: 3 }), // References one of the eight attributes by name
voraussetzung: new SchemaField({
talent: new StringField({ model: SkillDataModel }),
@ -34,6 +35,56 @@ export class SkillDataModel extends BaseItem {
* @param {Event} event The originating click event
* @private
*/
async roll() { }
async roll() {
console.log(this.parent)
let roll1 = new Roll("3d20", this.actor.getRollData());
let evaluated1 = (await roll1.evaluate())
const dsaDieRollEvaluated = this._evaluateRoll(evaluated1.terms[0].results, {
taw: dataset.taw,
werte: [this.system.probe[0], this.system.probe[1], this.system.probe[2]],
})
if (dsaDieRollEvaluated.tap >= 0) { // erfolg
evaluated1.toMessage({
speaker: ChatMessage.getSpeaker({actor: this.actor}),
flavor: ` ${dsaDieRollEvaluated.meisterlich?'Meisterlich geschafft':'Geschafft'} mit ${dsaDieRollEvaluated.tap} Punkten übrig`,
rollMode: game.settings.get('core', 'rollMode'),
})
} else { // misserfolg
evaluated1.toMessage({
speaker: ChatMessage.getSpeaker({actor: this.actor}),
flavor: ` ${dsaDieRollEvaluated.meisterlich?'Gepatzt':''} mit ${Math.abs(dsaDieRollEvaluated.tap)} Punkten daneben`,
rollMode: game.settings.get('core', 'rollMode'),
})
}
}
_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,
}
}
}

View File

@ -41,4 +41,103 @@ export class Character extends Actor {
}
async addSkillFromCompendiumByNameToActor(talentName, actor) {
const compendiumOfSkills = game.packs.get('DSA_4-1.talente-brw');
const talentId = compendiumOfSkills.index.find( skill => skill.name === talentName)
let talentObject = {}
const talent = await compendiumOfSkills.getDocument(talentId);
try {
const embeddedDocument = (await actor.createEmbeddedDocuments('Item', [talent]))[0]
if (embeddedDocument.type === "Skill") {
if (talent) {
talentObject = {
taw: 0,
talent: embeddedDocument.id,
}
}
}
} catch (error) {
console.error(`${talentName} not found in items`, error)
}
await actor.update({system: { talente: talentObject, ...actor.system.talente}})
}
/**
* Adds base skills according to the BRW to the given actor
* @param actor
* @returns {Promise<void>}
*/
async #createBaseSkills(actor) {
const talentsByName = [
"Athletik", "Klettern", "Körperbeherrschung", "Schleichen", "Schwimmen", "Selbstbeherrschung", "Sich Verstecken", "Singen", "Sinnenschärfe", "Tanzen", "Zechen",
"Menschenkenntnis", "Überreden",
"Fährtensuchen", "Orientierung", "Wildnisleben",
"Götter/Kulte", "Rechnen", "Sagen/Legenden",
"Heilkunde: Wunden", "Holzbearbeitung", "Kochen", "Lederverarbeitung", "Malen/Zeichnen", "Schneidern"
]
const talente = []
talentsByName.forEach(talentName => {
this.addSkillFromCompendiumByNameToActor(
talentName,
)
})
await actor.update({system: { talente: talente}})
}
/**
* Sets the attributes of the given actor to their default values
* @param actor
* @returns {Promise<void>}
*/
async #setBaseAttributes(actor) {
const startEigenschaften = {
"mu": {
start: 10,
aktuell: 10,
mod: 0
},
"kl": {
start: 10,
aktuell: 10,
mod: 0
},
"in": {
start: 10,
aktuell: 10,
mod: 0
},
"ch": {
start: 10,
aktuell: 10,
mod: 0
},
"ff": {
start: 10,
aktuell: 10,
mod: 0
},
"ge": {
start: 10,
aktuell: 10,
mod: 0
},
"ko": {
start: 10,
aktuell: 10,
mod: 0
},
"kk": {
start: 10,
aktuell: 10,
mod: 0
}
}
await actor.update({system: {attribute: startEigenschaften}})
}
}

View File

@ -1,62 +0,0 @@
import {DragDropDSA41} from "./DragDropDSA41.mjs";
export default function DragDropApplicationMixin(Base) {
return class DragDropApplication extends Base {
/** @override */
_onDragOver(event) {
const data = DragDropDSA41.getPayload(event);
DragDropDSA41.dropEffect = event.dataTransfer.dropEffect = (foundry.utils.getType(data) === "Object")
? this._dropBehavior(event, data) : "copy";
}
/* -------------------------------------------- */
/**
* The behavior for the dropped data. When called during the drop event, ensure this is called before awaiting
* anything or the drop behavior will be lost.
* @param {DragEvent} event The drag event.
* @param {object} [data] The drag payload.
* @returns {DropEffectValue}
*/
_dropBehavior(event, data) {
data ??= DragDropDSA41.getPayload(event);
const allowed = this._allowedDropBehaviors(event, data);
let behavior = DragDropDSA41.dropEffect ?? event.dataTransfer?.dropEffect;
if ( event.type === "dragover" ) {
if ( areKeysPressed(event, "dragMove") ) behavior = "move";
else if ( areKeysPressed(event, "dragCopy") ) behavior = "copy";
else behavior = this._defaultDropBehavior(event, data);
}
if ( (behavior !== "none") && !allowed.has(behavior) ) return allowed.first() ?? "none";
return behavior || "copy";
}
/* -------------------------------------------- */
/**
* Types of allowed drop behaviors based on the origin & target of a drag event.
* @param {DragEvent} event The drag event.
* @param {object} [data] The drag payload.
* @returns {Set<DropEffectValue>}
* @protected
*/
_allowedDropBehaviors(event, data) {
return new Set();
}
/* -------------------------------------------- */
/**
* Determine the default drop behavior for the provided operation.
* @param {DragEvent} event The drag event.
* @param {object} [data] The drag payload.
* @returns {DropEffectValue}
* @protected
*/
_defaultDropBehavior(event, data) {
return "copy";
}
};
}

View File

@ -1,54 +0,0 @@
export class DragDropDSA41 extends foundry.applications.ux.DragDrop {
/**
* Drop effect used for current drag operation.
* @type {DropEffectValue|null}
*/
static dropEffect = null;
/* -------------------------------------------- */
/**
* Stored drag event payload.
* @type {{ data: any, event: DragEvent }|null}
*/
static #payload = null;
/* -------------------------------------------- */
/** @override */
async _handleDragStart(event) {
await this.callback(event, "dragstart");
if ( event.dataTransfer.items.length ) {
console.log(event)
event.stopPropagation();
let data = event.dataTransfer.getData("application/json") || event.dataTransfer.getData("text/plain");
try { data = JSON.parse(data); } catch(err) {}
DragDropDSA41.#payload = data ? { event, data } : null;
} else {
DragDropDSA41.#payload = null;
}
}
/* -------------------------------------------- */
/** @override */
async _handleDragEnd(event) {
await this.callback(event, "dragend");
DragDropDSA41.dropEffect = null;
DragDropDSA41.#payload = null;
}
/* -------------------------------------------- */
/**
* Get the data payload for the current drag event.
* @param {DragEvent} event
* @returns {any}
*/
static getPayload(event) {
if ( !DragDropDSA41.#payload?.data ) return null;
return DragDropDSA41.#payload.data;
}
}

View File

@ -1,5 +1,3 @@
import {DragDropDSA41} from "../extensions/DragDropDSA41.mjs";
export class CharacterSheet extends ActorSheet {
/**@override */
static get defaultOptions() {
@ -24,10 +22,6 @@ export class CharacterSheet extends ActorSheet {
/** @override */
getData() {
// Retrieve the data structure from the base sheet. You can inspect or log
// the context variable to see the structure, but some key properties for
// sheets are the actor object, the data object, whether or not it's
// editable, the items array, and the effects array.
const context = super.getData();
// Use a safe clone of the actor data for further operations.
@ -36,6 +30,78 @@ export class CharacterSheet extends ActorSheet {
// Add the actor's data to context.data for easier access, as well as flags.
context.system = actorData.system;
context.flags = actorData.flags;
this.#addSkillsToContext(context)
this.#addAdvantagesToContext(context)
this.#addAttributesToContext(context)
return context;
}
#addSkillsToContext(context) {
const actorData = context.data;
context.skills = {};
context.flatSkills = [];
Object.values(actorData.items).forEach( (item, index) => {
if (item.type === "Skill") {
const talentGruppe = item.system.gruppe;
const eigenschaften = Object.values(item.system.probe);
const werte = [
{name: eigenschaften[0], value: this.prepareEigenschaftRoll(actorData, eigenschaften[0])},
{name: eigenschaften[1], value: this.prepareEigenschaftRoll(actorData, eigenschaften[1])},
{name: eigenschaften[2], value: this.prepareEigenschaftRoll(actorData, eigenschaften[2])}
]
if (context.skills[talentGruppe] == null) {
context.skills[talentGruppe] = [];
}
const obj = {
type: "talent",
gruppe: talentGruppe,
name: item.name,
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("/")})`
};
context.skills[talentGruppe].push(obj);
context.flatSkills.push(obj);
}
}
);
}
#addAdvantagesToContext(context) {
const actorAdvantages = {}
const actorData = context.data;
Object.values(actorData.items).forEach( (item) => {
if (item.type === "Advantage") {
actorAdvantages[item._id] = item;
}
}
);
if ( context.system.vornachteile.length >= 0) {
context.system.vornachteile.forEach( ( { vornachteil }, index) => {
context.vornachteile.push(
{
name: vornachteil.name,
value: vornachteil.value,
auswahl: vornachteil.auswahl,
}
)
})
}
}
#addAttributesToContext(context) {
const actorData = context.data;
context.attributes = [
{
eigenschaft: "mu",
@ -87,46 +153,7 @@ export class CharacterSheet extends ActorSheet {
},
];
context.skills = {};
context.flatSkills = [];
if ( context.system.talente?.length >= 0) {
context.system.talente.forEach( (talent, index) => {
if (talent.talent) {
const taw = talent.taw;
const talentObjekt = game.items.get(talent.talent);
console.log(talent);
const talentGruppe = talentObjekt.system.gruppe;
const eigenschaften = Object.values(talentObjekt.system.probe);
const werte = [
{name: eigenschaften[0], value: this.prepareEigenschaftRoll(actorData, eigenschaften[0])},
{name: eigenschaften[1], value: this.prepareEigenschaftRoll(actorData, eigenschaften[1])},
{name: eigenschaften[2], value: this.prepareEigenschaftRoll(actorData, eigenschaften[2])}
]
if (context.skills[talentGruppe] == null) {
context.skills[talentGruppe] = [];
}
const obj = {
type: "talent",
gruppe: talentGruppe,
name: talentObjekt.name,
taw: "" + taw,
tawPath: `system.talente.${index}.taw`,
werte,
rollEigenschaft1: werte[0].value,
rollEigenschaft2: werte[1].value,
rollEigenschaft3: werte[2].value,
probe: `(${eigenschaften.join("/")})`
};
context.skills[talentGruppe].push(obj);
context.flatSkills.push(obj);
}
})
}
return context;
}
prepareEigenschaftRoll(actorData, name) {
@ -165,6 +192,18 @@ export class CharacterSheet extends ActorSheet {
}
}
_onDropDocument(event, item) {
console.log(item)
}
_onDragStart(event) {
super._onDragStart(event);
const src = event.target
console.log(event)
event.dataTransfer.setData("plain/text", src.dataset.name);
}
_evaluateRoll(rolledDice, { taw, lowerThreshold = 1, upperThreshold = 20, countToMeisterlich = 3, countToPatzer = 3, werte = [] } ) {
let tap = taw;
let meisterlichCounter = 0;
@ -237,78 +276,51 @@ export class CharacterSheet extends ActorSheet {
this._onRoll(evt);
});
// Everything below here is only needed if the sheet is editable
if (!this.isEditable) return;
let handler = ev => this._onDragStart(ev);
// Find all items on the character sheet.
html.find('.talent.rollable').each((i, li) => {
// Add draggable attribute and dragstart listener.
li.setAttribute("draggable", true);
li.addEventListener("dragstart", handler, false);
});
}
#handleDroppedSkill(actor, skill) {
const array = Array.from(actor.items);
for ( let i = 0; i < array.length; i++ ) {
if (array[i].name === skill.name) {
return false;
}
}
}
static getElementByName(collection, id) {
const array = Array.from(collection);
for (const element of array) {
if (element._id === id) {
return element;
}
}
}
static onDroppedData(actor, characterSheet, data) {
const item = game.items.get(foundry.utils.parseUuid(data.uuid).id)
console.log();
let alreadyInSet = false;
let previousTaw = 0;
actor.system.talente.forEach(({taw, talent}) => {
if (talent._id === item._id) {
alreadyInSet = talent;
previousTaw = taw;
}
})
const myContent = `
TaW:
<input id="taw" type="number" value="${previousTaw}" />
`;
new Dialog({
title: `Talent ${item.name} ${alreadyInSet?'ersetzen':'hinzufügen'}`,
content: myContent,
buttons: {
button1: {
label: "hinzufügen",
callback: (html) => myCallback(html),
icon: `<i class="fas fa-check"></i>`
}
}
}).render(true);
async function myCallback(html) {
const taw = html.find("input#taw").val();
let index = actor.system.talente.findIndex( predicate => predicate.talent._id === alreadyInSet._id )
let sorted = [];
if (alreadyInSet) {
actor.system.talente[index].taw = taw;
sorted = actor.system.talente;
} else {
sorted = [{
taw: taw,
talent: {_id: item._id, name: item.name}
}, ...actor.system.talente].sort((a, b) => a.talent.name.localeCompare(b.talent.name));
const uuid = foundry.utils.parseUuid(data.uuid);
const collection = uuid.collection.index ?? uuid.collection;
const document = CharacterSheet.getElementByName(collection, uuid.id);
const {
name,
type
} = document
console.log(name, type)
switch (type) {
case "Skill":
return characterSheet.#handleDroppedSkill(actor, document); // on false cancel this whole operation
default:
return false;
}
const serialised = sorted.map(({taw, talent}) => {
return {
taw: taw,
talent: talent._id
}
});
await actor.update({
system: {
talente: [
...serialised
]
}
});
await characterSheet.render(true);
ui.notifications.info(`Talent ${item.name} auf TaW ${taw} hinzugefügt`);
}
actor.items.clear()
}
}

View File

@ -1,7 +1,4 @@
import {DragDropDSA41} from "../extensions/DragDropDSA41.mjs";
import DragDropApplicationMixin from "../extensions/DragDropApplicationMixin.mjs";
export class SkillSheet extends DragDropApplicationMixin(foundry.appv1.sheets.ItemSheet) {
export class SkillSheet extends ItemSheet {
/**@override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
@ -58,59 +55,4 @@ export class SkillSheet extends DragDropApplicationMixin(foundry.appv1.sheets.It
if (!this.isEditable) return;
}
/* -------------------------------------------- */
/* Drag & Drop */
/* -------------------------------------------- */
/** @override */
_allowedDropBehaviors(event, data) {
console.log(data, event);
if ( !data?.uuid ) return new Set(["copy", "link"]);
const allowed = new Set(["copy", "move", "link"]);
const s = foundry.utils.parseUuid(data.uuid);
const t = foundry.utils.parseUuid(this.document.uuid);
const sCompendium = s.collection instanceof foundry.documents.collections.CompendiumCollection;
const tCompendium = t.collection instanceof foundry.documents.collections.CompendiumCollection;
// If either source or target are within a compendium, but not inside the same compendium, move not allowed
if ( (sCompendium || tCompendium) && (s.collection !== t.collection) ) allowed.delete("move");
return allowed;
}
/* -------------------------------------------- */
/** @override */
_defaultDropBehavior(event, data) {
if ( !data?.uuid ) return "copy";
const d = foundry.utils.parseUuid(data.uuid);
const t = foundry.utils.parseUuid(this.document.uuid);
const base = d.embedded?.length ? "document" : "primary";
console.log(d, t, base);
return (d.collection === t.collection) && (d[`${base}Id`] === t[`${base}Id`])
&& (d[`${base}Type`] === t[`${base}Type`]) ? "move" : "copy";
}
/* -------------------------------------------- */
/** @inheritDoc */
async _onDragStart(event) {
await super._onDragStart(event);
if ( !this.document.isOwner || this.document.collection?.locked ) {
event.dataTransfer.effectAllowed = "copyLink";
}
}
_onDragOver(event) {
super._onDragOver(event);
console.log(event);
}
_dropBehavior(event, data) {
console.log(event, data);
return super._dropBehavior(event, data);
}
}

View File

@ -1,7 +1,4 @@
import {DragDropDSA41} from "../extensions/DragDropDSA41.mjs";
import DragDropApplicationMixin from "../extensions/DragDropApplicationMixin.mjs";
export class VornachteilSheet extends DragDropApplicationMixin(foundry.appv1.sheets.ItemSheet) {
export class VornachteilSheet extends ItemSheet {
/**@override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {

View File

@ -101,6 +101,22 @@ function calculateBirthdate(json) {
return `${day}. ${month} ${year} BF`
}
function mapSkills(rawJson) {
let talents = []
for (let talent in held.talentliste.talent) {
talent = held.talentliste.talent[talent]
let talentItem = game.items.getName(talent.name)
if (talentItem) {
let talentJson = {
talent: talentItem,
taw: talent.value,
}
talents.push(talentJson)
}
}
return talents
}
/**
* parses a json into a fitting character-json
* @param rawJson the json parsed from the Helden-Software XML
@ -248,19 +264,8 @@ function mapRawJson(rawJson) {
}
json.sonderfertigkeiten = specialAbilities
json.liturgien = liturgies
let talents = []
for (let talent in held.talentliste.talent) {
talent = held.talentliste.talent[talent]
let talentItem = game.items.getName(talent.name)
if (talentItem) {
let talentJson = {
talent: talentItem,
taw: talent.value,
}
talents.push(talentJson)
}
}
json.talente = talents
json.talente = mapSkills(rawJson)
let spells = []
/*for (let spell in held.zauberliste.zauber) {
spell = held.zauberliste.zauber[spell]

View File

@ -60,7 +60,11 @@
</div>
</div>
<div class="tab attributes" data-group="primary" data-tab="attributes">
<ul>
{{#each items}}
<li>{{this.name}}</li>
{{/each}}
</ul>
</div>
<div class="tab attributes" data-group="primary" data-tab="attributes">

View File

@ -1,4 +1,4 @@
<div class="block rollable {{this.type}} {{this.gruppe}}" data-taw="{{this.taw}}" data-rollEigenschaft1="{{this.rollEigenschaft1}}" data-rollEigenschaft2="{{this.rollEigenschaft2}}" data-rollEigenschaft3="{{this.rollEigenschaft3}}">
<div class="block rollable {{this.type}} {{this.gruppe}}" data-taw="{{this.taw}}'data-name="{{this.name}}" data-eigenschaft1="{{this.eigenschaft1}}" data-eigenschaft2="{{this.eigenschaft2}}" data-eigenschaft3="{{this.eigenschaft3}}" data-taw="{{this.taw}}" data-rollEigenschaft1="{{this.rollEigenschaft1}}" data-rollEigenschaft2="{{this.rollEigenschaft2}}" data-rollEigenschaft3="{{this.rollEigenschaft3}}">
<div class="die">
{{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }}