From 561e34d0ff9e9b86dac7b2c53e687a0a3e927e82 Mon Sep 17 00:00:00 2001 From: macniel Date: Thu, 16 Oct 2025 21:16:57 +0200 Subject: [PATCH] first push of charactersheet --- src/main.mjs | 2 +- src/module/sheets/character/attributes.mjs | 127 ++ src/module/sheets/character/combat.mjs | 112 ++ src/module/sheets/character/effects.mjs | 53 + src/module/sheets/character/equipment.mjs | 200 +++ src/module/sheets/character/liturgies.mjs | 109 ++ src/module/sheets/character/meta.mjs | 18 + src/module/sheets/character/skills.mjs | 81 + src/module/sheets/character/spells.mjs | 50 + src/module/sheets/characterSheet.mjs | 1406 ++++------------- src/module/sheets/groupSheet.mjs | 15 - src/templates/actor/actor-character-sheet.hbs | 814 ---------- src/templates/actor/character/main-sheet.hbs | 91 ++ .../actor/character/tab-attributes.hbs | 161 ++ src/templates/actor/character/tab-combat.hbs | 100 ++ src/templates/actor/character/tab-effects.hbs | 27 + .../actor/character/tab-equipment.hbs | 85 + .../actor/character/tab-liturgies.hbs | 202 +++ src/templates/actor/character/tab-meta.hbs | 49 + src/templates/actor/character/tab-skills.hbs | 85 + src/templates/actor/character/tab-spells.hbs | 49 + 21 files changed, 1947 insertions(+), 1889 deletions(-) create mode 100644 src/module/sheets/character/attributes.mjs create mode 100644 src/module/sheets/character/combat.mjs create mode 100644 src/module/sheets/character/effects.mjs create mode 100644 src/module/sheets/character/equipment.mjs create mode 100644 src/module/sheets/character/liturgies.mjs create mode 100644 src/module/sheets/character/meta.mjs create mode 100644 src/module/sheets/character/skills.mjs create mode 100644 src/module/sheets/character/spells.mjs delete mode 100644 src/templates/actor/actor-character-sheet.hbs create mode 100644 src/templates/actor/character/main-sheet.hbs create mode 100644 src/templates/actor/character/tab-attributes.hbs create mode 100644 src/templates/actor/character/tab-combat.hbs create mode 100644 src/templates/actor/character/tab-effects.hbs create mode 100644 src/templates/actor/character/tab-equipment.hbs create mode 100644 src/templates/actor/character/tab-liturgies.hbs create mode 100644 src/templates/actor/character/tab-meta.hbs create mode 100644 src/templates/actor/character/tab-skills.hbs create mode 100644 src/templates/actor/character/tab-spells.hbs diff --git a/src/main.mjs b/src/main.mjs index 21a59bc2..89239448 100644 --- a/src/main.mjs +++ b/src/main.mjs @@ -5,7 +5,7 @@ import {SkillDataModel} from "./module/data/skill.mjs"; import {SpellDataModel} from "./module/data/spell.mjs"; import {VornachteileDataModel} from "./module/data/vornachteile.mjs"; import {Character} from "./module/documents/character.mjs"; -import {CharacterSheet} from "./module/sheets/characterSheet.mjs"; +import CharacterSheet from "./module/sheets/characterSheet.mjs"; import {AdvantageSheet} from "./module/sheets/advantageSheet.mjs"; import {GroupDataModel} from "./module/data/group.mjs"; import {GroupSheet} from "./module/sheets/groupSheet.mjs"; diff --git a/src/module/sheets/character/attributes.mjs b/src/module/sheets/character/attributes.mjs new file mode 100644 index 00000000..230caa62 --- /dev/null +++ b/src/module/sheets/character/attributes.mjs @@ -0,0 +1,127 @@ +export default { + _prepareContext: async (context, options, object) => { + + const actorData = context.document + context.system = actorData.system + context.flags = actorData.flags + context.derived = context.document.system + context.originalName = actorData.name + context.name = context.derived.name ?? actorData.name + context.effects = actorData.effects ?? [] + context.advantages = [] + + const getModsOfAttribute = async (keyPath, object) => { + let returnValue = []; + Array.from(object.appliedEffects).forEach( + (e) => + e.changes.filter(c => c.key === keyPath).forEach(change => { + returnValue.push({ + name: e.name, + value: change.value > 0 ? "+" + change.value : "" + change.value, + icon: e.icon, + }) + })) + return returnValue; + } + + context.mods = { + "mu": await getModsOfAttribute('system.attribute.mu.mod', actorData), + "kl": await getModsOfAttribute('system.attribute.kl.mod', actorData), + "in": await getModsOfAttribute('system.attribute.in.mod', actorData), + "ch": await getModsOfAttribute('system.attribute.ch.mod', actorData), + "ff": await getModsOfAttribute('system.attribute.ff.mod', actorData), + "ge": await getModsOfAttribute('system.attribute.ge.mod', actorData), + "ko": await getModsOfAttribute('system.attribute.ko.mod', actorData), + "kk": await getModsOfAttribute('system.attribute.kk.mod', actorData), + "at": await getModsOfAttribute('system.at.mod', actorData), + "pa": await getModsOfAttribute('system.pa.mod', actorData), + "fk": await getModsOfAttribute('system.fk.mod', actorData), + + } + context.attributes = [ + { + eigenschaft: "mu", + name: "MU", + tooltip: "Mut", + wert: context.derived.attribute.mu.aktuell ?? 0, + }, + { + eigenschaft: "kl", + name: "KL", + tooltip: "Klugheit", + wert: context.derived.attribute.kl.aktuell ?? 0, + }, + { + eigenschaft: "in", + name: "IN", + tooltip: "Intuition", + wert: context.derived.attribute.in.aktuell ?? 0, + }, + { + eigenschaft: "ch", + name: "CH", + tooltip: "Charisma", + wert: context.derived.attribute.ch.aktuell ?? 0, + }, + { + eigenschaft: "ff", + name: "FF", + tooltip: "Fingerfertigkeit", + wert: context.derived.attribute.ff.aktuell ?? 0, + }, + { + eigenschaft: "ge", + name: "GE", + tooltip: "Geschicklichkeit", + wert: context.derived.attribute.ge.aktuell ?? 0, + }, + { + eigenschaft: "ko", + name: "KO", + tooltip: "Konstitution", + wert: context.derived.attribute.ko.aktuell ?? 0, + }, + { + eigenschaft: "kk", + name: "KK", + tooltip: "Körperkraft", + wert: context.derived.attribute.kk.aktuell ?? 0, + }, + + ] + + Object.values(actorData.items).forEach((item) => { + if (item.type === "Advantage") { + context.advantages.push({ + id: item._id, + name: item.name, + value: item.system.value, + options: item.system.auswahl, + description: item.system.description, + isAdvantage: !item.system.nachteil, + isDisadvantage: item.system.nachteil, + isBadAttribute: item.system.schlechteEigenschaft + }); + } + } + ); + + context.specialAbilities = []; + Object.values(actorData.items).forEach((item) => { + if (item.type === "SpecialAbility") { + context.specialAbilities.push({ + id: item._id, + name: item.name, + }); + } + } + ); + }, + _onRender: (context, options) => { + + }, + _getTabConfig: (group) => { + group.tabs.push({id: "attributes", group: "sheet", label: "Eigenschaften"}) + }, + template: `systems/DSA_4-1/templates/actor/character/tab-attributes.hbs` +} \ No newline at end of file diff --git a/src/module/sheets/character/combat.mjs b/src/module/sheets/character/combat.mjs new file mode 100644 index 00000000..ab4d9b48 --- /dev/null +++ b/src/module/sheets/character/combat.mjs @@ -0,0 +1,112 @@ +import {ActionManager} from "../actions/action-manager.mjs"; + +export default { + _prepareContext: async (context, object) => { + + const actorData = context.document + context.system = actorData.system + context.flags = actorData.flags + context.derived = context.document.system + context.originalName = actorData.name + context.name = context.derived.name ?? actorData.name + context.effects = actorData.effects ?? [] + + const findEquipmentOnSlot = (slot, setNumber, object) => { + return object.items.get(object.system.heldenausruestung[setNumber]?.[slot]) + } + + const am = new ActionManager(actorData) + context.actions = am.evaluate() + + + context.inidice = actorData.system.ini.wuerfel + context.inivalue = actorData.system.ini.aktuell + context.inimod = actorData.system.ini.mod + + context.aupper = Math.min((actorData.system.aup.aktuell / actorData.system.aup.max) * 100, 100) + context.lepper = Math.min((actorData.system.lep.aktuell / actorData.system.lep.max) * 100, 100) + context.keper = Math.min((actorData.system.kap.aktuell / actorData.system.kap.max) * 100, 100) + context.aspper = Math.min((actorData.system.asp.aktuell / actorData.system.asp.max) * 100, 100) + context.lepcurrent = actorData.system.lep.aktuell ?? 0 + + context.aupcurrent = actorData.system.aup.aktuell ?? 0 + + const fernkampf = findEquipmentOnSlot("fernkampf", actorData.system.setEquipped, actorData) + const links = findEquipmentOnSlot("links", actorData.system.setEquipped, actorData) + const rechts = findEquipmentOnSlot("rechts", actorData.system.setEquipped, actorData) + context.attacks = []; + + if (fernkampf) { + const fkitems = fernkampf.system.rangedSkills.map((skillInQuestion) => actorData.items.find(p => p.name === skillInQuestion)) + fkitems.forEach(async skill => { + const obj = await skill + context.attacks.push({ + name: obj.name, + using: fernkampf.name, + atroll: `1d20cs<${object.system.fk.aktuell + obj.system.at}`, + at: `${object.system.fk.aktuell + obj.system.at}`, + tproll: `${fernkampf.system.rangedAttackDamage}`, // TODO consider adding TP/KK mod and Range mod + tp: `${fernkampf.system.rangedAttackDamage}`, + iniroll: `(${context.inidice})d6 + ${context.inivalue + fernkampf.system.iniModifier ?? 0}`, + ini: `${context.inidice}w6 + ${context.inivalue + fernkampf.system.iniModifier ?? 0}`, + }) + }) + } + if (links) { + const meitems = [] + links.system.meleeSkills.forEach((skillInQuestion) => { + const item = actorData.items.find(p => p.name === skillInQuestion) + if (item) { + meitems.push(item) + } + }) + meitems.forEach(skill => { + const obj = skill + context.attacks.push({ + name: obj.name, + using: links.name, + atroll: `1d20cs<${object.system.at.links.aktuell + obj.system.at + links.system.attackModifier}`, // TODO consider adding W/M + at: `${object.system.at.links.aktuell + obj.system.at + links.system.attackModifier}`, + paroll: `1d20cs<${object.system.pa.links.aktuell + obj.system.pa + links.system.parryModifier}`, // TODO consider adding W/M + pa: `${object.system.pa.links.aktuell + obj.system.pa + links.system.parryModifier}`, + tproll: `${links.system.meleeAttackDamage}`, // TODO consider adding TP/KK mod + tp: `${links.system.meleeAttackDamage}`, + iniroll: `(${context.inidice})d6 + ${context.inivalue + links.system.iniModifier ?? 0}`, + ini: `${context.inidice}w6 + ${context.inivalue + links.system.iniModifier ?? 0}`, + }) + }) + } + if (rechts) { + const meitems = [] + rechts.system.meleeSkills.forEach((skillInQuestion) => { + const item = actorData.items.find(p => p.name === skillInQuestion) + if (item) { + meitems.push(item) + } + }) + meitems.forEach(skill => { + const obj = skill + context.attacks.push({ + name: obj.name, + using: rechts.name, + atroll: `1d20cs<${object.system.at.rechts.aktuell + obj.system.at + rechts.system.attackModifier}`, // TODO consider adding W/M + at: `${object.system.at.rechts.aktuell + obj.system.at + rechts.system.attackModifier}`, + paroll: `1d20cs<${object.system.pa.rechts.aktuell + obj.system.pa + rechts.system.parryModifier}`, // TODO consider adding W/M + pa: `${object.system.pa.rechts.aktuell + obj.system.pa + rechts.system.parryModifier}`, + tproll: `${rechts.system.meleeAttackDamage}`, // TODO consider adding TP/KK mod + tp: `${rechts.system.meleeAttackDamage}`, + iniroll: `(${context.inidice})d6 + ${context.inivalue + rechts.system.iniModifier ?? 0}`, + ini: `${context.inidice}w6 + ${context.inivalue + rechts.system.iniModifier ?? 0}`, + }) + }) + } + + }, + _onRender: (context, options) => { + + }, + _getTabConfig: (group) => { + group.tabs.push({id: "combat", group: "sheet", label: "Kampf"}) + }, + template: `systems/DSA_4-1/templates/actor/character/tab-combat.hbs` +} \ No newline at end of file diff --git a/src/module/sheets/character/effects.mjs b/src/module/sheets/character/effects.mjs new file mode 100644 index 00000000..6c817e7d --- /dev/null +++ b/src/module/sheets/character/effects.mjs @@ -0,0 +1,53 @@ +export default { + _prepareContext: (context, object) => { + + const actorData = context.document + context.spells = [] + context.system = actorData.system + context.flags = actorData.flags + context.derived = context.document.system + context.originalName = actorData.name + context.name = context.derived.name ?? actorData.name + context.effects = actorData.effects ?? [] + + context.isGM = game.user.isGM + context.effects = [] + Object.values(actorData.items).forEach((item, index) => { + if (item.type === "ActiveEffect") { + const effect = item.effects[0]; + const conditions = [] + + if (effect) { + effect.changes.forEach(change => { + if (change.key.indexOf("wunden") === -1) { + const key = change.key + .replace(/system\./g, "") + .replace(/\.mod/g, "") + .replace(/attribute./g, "") + .replace(/.links/g, "(Links)") + .replace(/.rechts/g, "(Rechts)") + const value = Number(change.value) > 0 ? "+" + change.value : change.value + conditions.push( + `${key}${value}` + ) + } + }) + } + + context.effects.push({ + name: item.name, + conditions: conditions.join(" "), + id: item._id, + actor: actorData._id + }); + } + }) + }, + _onRender: (context, options) => { + + }, + _getTabConfig: (group) => { + group.tabs.push({id: "effects", group: "sheet", label: "Effekte"}) + }, + template: `systems/DSA_4-1/templates/actor/character/tab-effects.hbs` +} \ No newline at end of file diff --git a/src/module/sheets/character/equipment.mjs b/src/module/sheets/character/equipment.mjs new file mode 100644 index 00000000..680a0538 --- /dev/null +++ b/src/module/sheets/character/equipment.mjs @@ -0,0 +1,200 @@ +import {PlayerCharacterDataModel} from "../../data/character.mjs"; + +export default { + _prepareContext: (context) => { + + const actorData = context.document + context.spells = [] + context.system = actorData.system + context.flags = actorData.flags + context.derived = context.document.system + context.originalName = actorData.name + context.name = context.derived.name ?? actorData.name + context.effects = actorData.effects ?? [] + + const isWorn = (itemId, object) => { + + const slots = PlayerCharacterDataModel.getSlots() + const set = object.system.heldenausruestung[object.system.setEquipped] + if (set) { + for (const slot of slots) { + const equipmentSlotId = set[slot] + if (equipmentSlotId === itemId) { + return slot + } + } + } + + return false + } + + context.equipments = [] + context.carryingweight = 0 + Object.values(actorData.items).forEach((item, index) => { + if (item.type === "Equipment") { + + // worn items are halved weight + + let effectiveWeight = item.system.weight ?? 0 + if (isWorn(item._id, object)) { + effectiveWeight = item.system.weight ? item.system.weight / 2 : 0 + } + + context.equipments.push({ + index: index, + id: item._id, + quantity: item.system.quantity, + name: item.name, + icon: item.img ?? "", + weight: item.system.weight, + worn: isWorn(item._id, object) + }) + context.carryingweight += item.system.quantity * effectiveWeight; + } + }) + context.maxcarryingcapacity = actorData.system.attribute.kk.aktuell + context.carryingpercentage = Math.min((context.carryingweight / context.maxcarryingcapacity) * 100, 100); + + const maxSets = 3 + const romanNumerals = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"] + context.sets = [] + for (let setIndex = 0; setIndex < maxSets; setIndex++) { + + context.sets.push({ + tab: "set" + (setIndex + 1), + name: romanNumerals[setIndex], + index: setIndex, + slots: [ + { + target: "links", + id: actorData.system.heldenausruestung[setIndex]?.links, + name: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.links)?.name, + icon: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.links)?.img + }, + { + target: "rechts", + id: actorData.system.heldenausruestung[setIndex]?.rechts, + name: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.rechts)?.name, + icon: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.rechts)?.img + }, + { + target: "brust", + id: actorData.system.heldenausruestung[setIndex]?.brust, + name: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.brust)?.name, + icon: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.brust)?.img + }, + { + target: "ruecken", + id: actorData.system.heldenausruestung[setIndex]?.ruecken, + name: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.ruecken)?.name, + icon: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.ruecken)?.img + }, + { + target: "kopf", + id: actorData.system.heldenausruestung[setIndex]?.kopf, + name: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.kopf)?.name, + icon: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.kopf)?.img + }, + { + target: "fernkampf", + id: actorData.system.heldenausruestung[setIndex]?.fernkampf, + name: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.fernkampf)?.name, + icon: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.fernkampf)?.img + }, + { + target: "munition", + id: actorData.system.heldenausruestung[setIndex]?.munition, + name: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.munition)?.name, + icon: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.munition)?.img + }, + { + target: "armlinks", + id: actorData.system.heldenausruestung[setIndex]?.armlinks, + name: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.armlinks)?.name, + icon: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.armlinks)?.img + }, + { + target: "armrechts", + id: actorData.system.heldenausruestung[setIndex]?.armrechts, + name: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.armrechts)?.name, + icon: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.armrechts)?.img + }, + { + target: "bauch", + id: actorData.system.heldenausruestung[setIndex]?.bauch, + name: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.bauch)?.name, + icon: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.bauch)?.img + }, + { + target: "beinlinks", + id: actorData.system.heldenausruestung[setIndex]?.beinlinks, + name: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.beinlinks)?.name, + icon: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.beinlinks)?.img + }, + { + target: "beinrechts", + id: actorData.system.heldenausruestung[setIndex]?.beinrechts, + name: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.beinrechts)?.name, + icon: actorData.items.get(actorData.system.heldenausruestung[setIndex]?.beinrechts)?.img + } + ] + }) + } + }, + _onRender: (context, options, element) => { + const mapAllSets = () => { + const updateObject = {} + Array.from(context.document.system.heldenausruestung).forEach((equipmentSet, index) => { + updateObject[`system.heldenausruestung.${index}.links`] = equipmentSet.links; + updateObject[`system.heldenausruestung.${index}.rechts`] = equipmentSet.rechts; + updateObject[`system.heldenausruestung.${index}.brust`] = equipmentSet.brust; + updateObject[`system.heldenausruestung.${index}.bauch`] = equipmentSet.bauch; + updateObject[`system.heldenausruestung.${index}.ruecken`] = equipmentSet.ruecken; + updateObject[`system.heldenausruestung.${index}.kopf`] = equipmentSet.kopf; + updateObject[`system.heldenausruestung.${index}.fernkampf`] = equipmentSet.fernkampf; + updateObject[`system.heldenausruestung.${index}.munition`] = equipmentSet.munition; + updateObject[`system.heldenausruestung.${index}.armlinks`] = equipmentSet.armlinks; + updateObject[`system.heldenausruestung.${index}.armrechts`] = equipmentSet.armrechts; + updateObject[`system.heldenausruestung.${index}.beinlinks`] = equipmentSet.beinlinks; + updateObject[`system.heldenausruestung.${index}.beinrechts`] = equipmentSet.beinrechts; + + }) + return updateObject; + } + + new foundry.applications.ux.ContextMenu(element, '.equipped', [ + { + name: "Gegenstand vom Set entfernen", + callback: (event) => { + const {setId, target, actor} = event[0].dataset + + const updateObject = mapAllSets() + updateObject[`system.heldenausruestung.${setId}.${target}`] = null; + + object.update(updateObject); + }, + condition: () => true + } + ], { + jQuery: false + }); + + new foundry.applications.ux.ContextMenu(element, '.equipment', [ + { + name: "Aus dem Inventar entfernen", + icon: '', + callback: (event) => { + // TODO find id on heldenausruestung to remove the worn items as well + object.deleteEmbeddedDocuments('Item', [event[0].dataset.id]) + }, + condition: () => true + } + ], { + jQuery: false + }); + }, + _getTabConfig: (group) => { + group.tabs.push({id: "equipment", group: "sheet", label: "Ausrüstung"}) + }, + template: `systems/DSA_4-1/templates/actor/character/tab-equipment.hbs` +} \ No newline at end of file diff --git a/src/module/sheets/character/liturgies.mjs b/src/module/sheets/character/liturgies.mjs new file mode 100644 index 00000000..196ac767 --- /dev/null +++ b/src/module/sheets/character/liturgies.mjs @@ -0,0 +1,109 @@ +import {LiturgyData} from "../../data/miracle/liturgydata.mjs"; + +export default { + _prepareContext: (context) => { + + const actorData = context.document + context.system = actorData.system + context.flags = actorData.flags + context.derived = context.document.system + context.originalName = actorData.name + context.name = context.derived.name ?? actorData.name + + context.effects = actorData.effects ?? [] + context.liturgies = []; + context.blessings = []; + + Object.values(actorData.items).forEach((item, index) => { + if (item.type === "Blessing") { + context.blessings.push({ + deity: item.system.gottheit, + value: item.system.wert + }) + } + }) + Object.values(actorData.items).forEach((item, index) => { + if (item.type === "Liturgy") { + + context.blessings.forEach(({deity, value}) => { + let insertObject = context.liturgies.find(p => p.deity === deity); + if (!insertObject) { + insertObject = { + deity: deity, + lkp: value, + O: [], + I: [], + II: [], + III: [], + IV: [], + V: [], + VI: [], + VII: [], + VIII: [], + "NA": [], + countO: 1, + countI: 1, + countII: 1, + countIII: 1, + countIV: 1, + countV: 1, + countVI: 1, + countVII: 1, + countVIII: 1, + countNA: 0, + total: 3, + + } + context.liturgies.push(insertObject); + } + + // sort by rank + const rankData = LiturgyData.getRankOfLiturgy(item.system, deity) + if (rankData) { + let {index, name, lkp, mod, costKaP} = rankData; + + insertObject["count" + name] = insertObject["count" + name] + 1; + + insertObject[name].push({ + id: item._id, + name: item.name, + lkpReq: lkp, + lkpMod: mod, + costKaP, + rank: index, // get effective liturgy rank based on deity + liturgiekenntnis: deity, + }) + insertObject.total = insertObject.total + 2; + + } + }) + } + }) + + + // clean up counter + Object.values(context.liturgies).forEach((litObject) => { + + if (litObject.I.length === 0) litObject.countI = false; + if (litObject.II.length === 0) litObject.countII = false; + if (litObject.III.length === 0) litObject.countIII = false; + if (litObject.IV.length === 0) litObject.countIV = false; + if (litObject.V.length === 0) litObject.countV = false; + if (litObject.VI.length === 0) litObject.countVI = false; + if (litObject.VII.length === 0) litObject.countVII = false; + if (litObject.VIII.length === 0) litObject.countVIII = false; + if (litObject.NA.length === 0) litObject.countNA = false; + + + }) + + context.hasLiturgies = context.blessings.length > 0; + }, + _onRender: (context, options) => { + + }, + _getTabConfig: (group) => { + group.tabs.push({id: "liturgies", group: "sheet", label: "Liturgien"}) + }, + template: `systems/DSA_4-1/templates/actor/character/tab-liturgies.hbs` +} \ No newline at end of file diff --git a/src/module/sheets/character/meta.mjs b/src/module/sheets/character/meta.mjs new file mode 100644 index 00000000..75ed6f50 --- /dev/null +++ b/src/module/sheets/character/meta.mjs @@ -0,0 +1,18 @@ +export default { + _prepareContext: (context, object) => { + const actorData = context.document + context.system = actorData.system + context.flags = actorData.flags + context.derived = context.document.system + context.originalName = actorData.name + context.name = context.derived.name ?? actorData.name + context.effects = actorData.effects ?? [] + }, + _onRender: (context, options) => { + + }, + _getTabConfig: (group) => { + group.tabs.push({id: "meta", group: "sheet", label: "Meta"}) + }, + template: `systems/DSA_4-1/templates/actor/character/tab-meta.hbs` +} \ No newline at end of file diff --git a/src/module/sheets/character/skills.mjs b/src/module/sheets/character/skills.mjs new file mode 100644 index 00000000..78e6b307 --- /dev/null +++ b/src/module/sheets/character/skills.mjs @@ -0,0 +1,81 @@ +export default { + _prepareContext: (context) => { + + const actorData = context.document + context.spells = [] + context.system = actorData.system + context.flags = actorData.flags + context.derived = context.document.system + context.originalName = actorData.name + context.name = context.derived.name ?? actorData.name + context.effects = actorData.effects ?? [] + + const prepareEigenschaftRoll = (actorData, name) => { + if (name && name !== "*") { + return actorData.system.attribute[name.toLowerCase()].aktuell + } else { + return 0 + } + } + + + 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: prepareEigenschaftRoll(actorData, eigenschaften[0])}, + {name: eigenschaften[1], value: prepareEigenschaftRoll(actorData, eigenschaften[1])}, + {name: eigenschaften[2], value: 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("/")})`, + id: item._id, + at: item.system.at, + pa: item.system.pa, + komplexität: item.system.komplexität + }; + + if (talentGruppe === "Kampf") { + + if (item.system.pa != null) { // has no parry value so it must be ranged talent (TODO: but it isnt as there can be combatstatistics which has no pa value assigned to) + obj.at = item.system.at + context.derived.at.aktuell + obj.pa = item.system.pa + context.derived.pa.aktuell + } else { + obj.at = item.system.at + context.derived.fk.aktuell + } + } + + context.skills[talentGruppe].push(obj); + context.flatSkills.push(obj); + } + } + ); + }, + _onRender: (context, options) => { + + }, + _getTabConfig: (group) => { + group.tabs.push({id: "skills", group: "sheet", label: "Talente"}) + }, + template: `systems/DSA_4-1/templates/actor/character/tab-skills.hbs` +} \ No newline at end of file diff --git a/src/module/sheets/character/spells.mjs b/src/module/sheets/character/spells.mjs new file mode 100644 index 00000000..9c33ad0d --- /dev/null +++ b/src/module/sheets/character/spells.mjs @@ -0,0 +1,50 @@ +export default { + _prepareContext: (context) => { + + const actorData = context.document + context.spells = [] + context.system = actorData.system + context.flags = actorData.flags + context.derived = context.document.system + context.originalName = actorData.name + context.name = context.derived.name ?? actorData.name + context.effects = actorData.effects ?? [] + + const cleanUpMerkmal = (merkmale) => { + return merkmale.split(",").map((merkmal) => merkmal.trim()) + } + + + Object.values(actorData.items).forEach((item, index) => { + if (item.type === "Spell") { + const eigenschaften = 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])} + ] + context.spells.push({ + id: item._id, + name: item.name, + zfw: item.system.zfw, + hauszauber: item.system.hauszauber, + merkmal: cleanUpMerkmal(item.system.merkmal), + rollEigenschaft1: werte[0].value, + rollEigenschaft2: werte[1].value, + rollEigenschaft3: werte[2].value, + eigenschaft1: werte[0].name, + eigenschaft2: werte[1].name, + eigenschaft3: werte[2].name, + }) + } + }) + context.hasSpells = context.spells.length > 0; + }, + _onRender: (context, options) => { + + }, + _getTabConfig: (group) => { + group.tabs.push({id: "spells", group: "sheet", label: "Zauber"}) + }, + template: `systems/DSA_4-1/templates/actor/character/tab-spells.hbs` +} \ No newline at end of file diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index bb6f9d84..69716a1b 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -1,145 +1,163 @@ -import {PlayerCharacterDataModel} from "../data/character.mjs"; -import {ActionManager} from "./actions/action-manager.mjs"; -import {LiturgyData} from "../data/miracle/liturgydata.mjs"; -import {ModifyLiturgy} from "../dialog/modify-liturgy.mjs"; +import Meta from "./character/meta.mjs" +import Attributes from "./character/attributes.mjs" +import Combat from "./character/combat.mjs" +import Equipment from "./character/equipment.mjs" +import Skills from "./character/skills.mjs" +import Spells from "./character/spells.mjs" +import Liturgies from "./character/liturgies.mjs" +import Effects from "./character/effects.mjs" -export class CharacterSheet extends foundry.appv1.sheets.ActorSheet { - /**@override */ - static get defaultOptions() { - return foundry.utils.mergeObject(super.defaultOptions, { - classes: ['dsa41', 'sheet', 'actor', 'character'], - width: 1100, - height: 480, +const {HandlebarsApplicationMixin} = foundry.applications.api +const {ActorSheetV2} = foundry.applications.sheets +const {ContextMenu} = foundry.applications.ux + + +class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { + + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + position: {width: 1100, height: 640}, + classes: ['dsa41', 'sheet', 'actor', 'character'], + tag: 'form', + form: { + submitOnChange: true, + closeOnSubmit: false, + handler: CharacterSheet.#onSubmitForm + }, + window: { + resizable: true, + }, + actions: { + roll: CharacterSheet.#dieRoll, + editImage: ActorSheetV2.DEFAULT_OPTIONS.actions.editImage, + openEmbeddedDocument: CharacterSheet.#openEmbeddedDocument, + } + } + + static TABS = { + sheet: { tabs: [ - { - navSelector: '.sheet-tabs', - contentSelector: '.sheet-body', - initial: 'description', - }, + {id: 'meta', group: 'sheet', label: 'Meta'}, ], - }); - } - - /** @override */ - get template() { - return `systems/DSA_4-1/templates/actor/actor-character-sheet.hbs`; - } - - static onDroppedData(actor, characterSheet, data) { - 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 - case "Advantage": - return characterSheet.#handleDroppedAdvantage(actor, document); - case "ActiveEffect": - return characterSheet.#handleDroppedActiveEffect(actor, document); - case "Equipment": - return characterSheet.#handleDroppedEquipment(actor, document); - case "Liturgy": - return characterSheet.#handleDroppedLiturgy(actor, document); - case "SpecialAbility": - return characterSheet.#handleDroppedSpecialAbility(actor, document); - default: - return false; - } - - } - - static getElementByName(collection, id) { - const array = Array.from(collection); - for (const element of array) { - if (element._id === id) { - return element; - } + initial: 'meta' } } - #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("/")})`, - id: item._id, - at: item.system.at, - pa: item.system.pa, - komplexität: item.system.komplexität - }; - - if (talentGruppe === "Kampf") { - - if (item.system.pa != null) { // has no parry value so it must be ranged talent (TODO: but it isnt as there can be combatstatistics which has no pa value assigned to) - obj.at = item.system.at + context.derived.at.aktuell - obj.pa = item.system.pa + context.derived.pa.aktuell - } else { - obj.at = item.system.at + context.derived.fk.aktuell - } - } - - context.skills[talentGruppe].push(obj); - context.flatSkills.push(obj); - } - } - ); + /** @inheritDoc */ + static PARTS = { + form: { + template: `systems/DSA_4-1/templates/actor/character/main-sheet.hbs` + }, + meta: { + template: Meta.template + }, + attributes: { + template: Attributes.template + }, + combat: { + template: Combat.template + }, + equipment: { + template: Equipment.template + }, + skills: { + template: Skills.template + }, + liturgies: { + template: Liturgies.template + }, + effects: { + template: Effects.template + } } - #cleanUpMerkmal(merkmale) { - return merkmale.split(",").map((merkmal) => merkmal.trim()) + static #dieRoll(event) { + event.preventDefault() + const dataset = event.currentTarget.dataset + if (dataset.roll) { + let label = dataset.label ? `[Attribut] ${dataset.label}` : '' + let roll = new Roll(dataset.roll, this.actor.getRollData()) + roll.toMessage({ + speaker: ChatMessage.getSpeaker({actor: this.actor}), + flavor: label, + rollMode: game.settings.get('core', 'rollMode'), + }); + return roll + } + } + + static #openEmbeddedDocument(documentId) { + this.object.items.get(documentId).sheet.render(true) + } + + /** + * Handle form submission + * @this {AdvantageSheet} + * @param {SubmitEvent} event + * @param {HTMLFormElement} form + * @param {FormDataExtended} formData + */ + static async #onSubmitForm(event, form, formData) { + event.preventDefault() + + await this.document.update(formData.object) // Note: formData.object + } + + _getTabsConfig(group) { + const tabs = foundry.utils.deepClone(super._getTabsConfig(group)) + Attributes._getTabConfig(tabs) + Combat._getTabConfig(tabs) + Equipment._getTabConfig(tabs) + Skills._getTabConfig(tabs) + Spells._getTabConfig(tabs) + Liturgies._getTabConfig(tabs) + Effects._getTabConfig(tabs) + return tabs + } + + async _preparePartContext(partId, context) { + switch (partId) { + case "meta": + Meta._prepareContext(context, this.object) + break + case "attributes": + await Attributes._prepareContext(context, this.object) + break + case "combat": + await Combat._prepareContext(context, this.object) + break + case "equipment": + Equipment._prepareContext(context, this.object) + break + case "skills": + Skills._prepareContext(context, this.object) + break + case "spells": + Spells._prepareContext(context, this.object) + break + case "liturgies": + Liturgies._prepareContext(context, this.object) + break + case "effects": + Effects._prepareContext(context, this.object) + break + } } /** @override */ - async getData() { - const context = super.getData(); + async _prepareContext(options) { + const context = await super._prepareContext(options) + const actorData = context.document + context.system = actorData.system + context.flags = actorData.flags + context.derived = context.document.system + context.originalName = actorData.name + context.name = context.derived.name ?? actorData.name + context.effects = actorData.effects ?? [] - - // Use a safe clone of the actor data for further operations. - const actorData = context.data; - - // Add the actor's data to context.data for easier access, as well as flags. - context.system = actorData.system; - context.flags = actorData.flags; - context.derived = context.document.system; - context.originalName = actorData.name; - context.name = context.derived.name ?? actorData.name; - context.effects = actorData.effects ?? []; - - context.maxWounds = actorData.system.wunden.max ?? 3; - context.wounds = actorData.system.wunden.aktuell ?? 0; - context.woundsFilled = []; + context.maxWounds = actorData.system.wunden.max ?? 3 + context.wounds = actorData.system.wunden.aktuell ?? 0 + context.woundsFilled = [] for (let i = 1; i <= context.maxWounds; i++) { context.woundsFilled[i] = i <= context.wounds } @@ -148,950 +166,220 @@ export class CharacterSheet extends foundry.appv1.sheets.ActorSheet { context.trefferzonen = game.settings.get("DSA_4-1", "optional_trefferzonen") context.ausdauer = game.settings.get("DSA_4-1", "optional_ausdauer") - - this.#addEffectsToContext(context) - this.#addSkillsToContext(context) - this.#addAdvantagesToContext(context) - this.#addSpecialAbilitiesToContext(context) - await this.#addAttributesToContext(context) - this.#addEquipmentsToContext(context) - await this.#addCombatStatistics(context) - this.#addActionsToContext(context) - this.#addSpellsToContext(context) - this.#addLiturgiesToContext(context) return context; } - #addEffectsToContext(context) { - const actorData = context.data; + _onRender(context, options) { + Meta._onRender(context, options, this.element) + Attributes._onRender(context, options, this.element) + Combat._onRender(context, options, this.element) + Effects._onRender(context, options, this.element) + Equipment._onRender(context, options, this.element) + Liturgies._onRender(context, options, this.element) + Skills._onRender(context, options, this.element) + Spells._onRender(context, options, this.element) + } - context.isGM = game.user.isGM - context.effects = []; - Object.values(actorData.items).forEach((item, index) => { - if (item.type === "ActiveEffect") { - const effect = item.effects[0]; - const conditions = [] + /* showAdjustAttributeDialog(attributeName, attributeField, previousValue) { + const thisActor = this; + const myContent = ` + Value: + + `; - if (effect) { - effect.changes.forEach(change => { - if (change.key.indexOf("wunden") === -1) { - const key = change.key - .replace(/system\./g, "") - .replace(/\.mod/g, "") - .replace(/attribute./g, "") - .replace(/.links/g, "(Links)") - .replace(/.rechts/g, "(Rechts)") - const value = Number(change.value) > 0 ? "+" + change.value : change.value; - conditions.push( - `${key}${value}` - ) - } - }) + function updateAttribute(html) { + const value = html.find("input#attributeValue").val(); + const attribute = {} + attribute[attributeField.toLowerCase()] = { + aktuell: value } - - context.effects.push({ - name: item.name, - conditions: conditions.join(" "), - id: item._id, - actor: actorData._id - }); + thisActor.object.update({system: {attribute}}) } - }) - } - #addSpellsToContext(context) { - const actorData = context.data; - context.spells = []; - Object.values(actorData.items).forEach((item, index) => { - if (item.type === "Spell") { - const eigenschaften = 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])} - ] - context.spells.push({ - id: item._id, - name: item.name, - zfw: item.system.zfw, - hauszauber: item.system.hauszauber, - merkmal: this.#cleanUpMerkmal(item.system.merkmal), - rollEigenschaft1: werte[0].value, - rollEigenschaft2: werte[1].value, - rollEigenschaft3: werte[2].value, - eigenschaft1: werte[0].name, - eigenschaft2: werte[1].name, - eigenschaft3: werte[2].name, - }) - } - }) - context.hasSpells = context.spells.length > 0; - } - - async #getModsOfAttribute(keyPath) { - let returnValue = []; - Array.from(this.object.appliedEffects).forEach( - (e) => - e.changes.filter(c => c.key === keyPath).forEach(change => { - returnValue.push({ - name: e.name, - value: change.value > 0 ? "+" + change.value : "" + change.value, - icon: e.icon, - }) - })) - return returnValue; - } - - async #addAttributesToContext(context) { - context.mods = { - "mu": await this.#getModsOfAttribute('system.attribute.mu.mod'), - "kl": await this.#getModsOfAttribute('system.attribute.kl.mod'), - "in": await this.#getModsOfAttribute('system.attribute.in.mod'), - "ch": await this.#getModsOfAttribute('system.attribute.ch.mod'), - "ff": await this.#getModsOfAttribute('system.attribute.ff.mod'), - "ge": await this.#getModsOfAttribute('system.attribute.ge.mod'), - "ko": await this.#getModsOfAttribute('system.attribute.ko.mod'), - "kk": await this.#getModsOfAttribute('system.attribute.kk.mod'), - "at": await this.#getModsOfAttribute('system.at.mod'), - "pa": await this.#getModsOfAttribute('system.pa.mod'), - "fk": await this.#getModsOfAttribute('system.fk.mod'), - - } - context.attributes = [ - { - eigenschaft: "mu", - name: "MU", - tooltip: "Mut", - wert: context.derived.attribute.mu.aktuell ?? 0, - }, - { - eigenschaft: "kl", - name: "KL", - tooltip: "Klugheit", - wert: context.derived.attribute.kl.aktuell ?? 0, - }, - { - eigenschaft: "in", - name: "IN", - tooltip: "Intuition", - wert: context.derived.attribute.in.aktuell ?? 0, - }, - { - eigenschaft: "ch", - name: "CH", - tooltip: "Charisma", - wert: context.derived.attribute.ch.aktuell ?? 0, - }, - { - eigenschaft: "ff", - name: "FF", - tooltip: "Fingerfertigkeit", - wert: context.derived.attribute.ff.aktuell ?? 0, - }, - { - eigenschaft: "ge", - name: "GE", - tooltip: "Geschicklichkeit", - wert: context.derived.attribute.ge.aktuell ?? 0, - }, - { - eigenschaft: "ko", - name: "KO", - tooltip: "Konstitution", - wert: context.derived.attribute.ko.aktuell ?? 0, - }, - { - eigenschaft: "kk", - name: "KK", - tooltip: "Körperkraft", - wert: context.derived.attribute.kk.aktuell ?? 0, - }, - - ]; - - } - - #addAdvantagesToContext(context) { - context.advantages = []; - const actorData = context.data; - Object.values(actorData.items).forEach((item) => { - if (item.type === "Advantage") { - context.advantages.push({ - id: item._id, - name: item.name, - value: item.system.value, - options: item.system.auswahl, - description: item.system.description, - isAdvantage: !item.system.nachteil, - isDisadvantage: item.system.nachteil, - isBadAttribute: item.system.schlechteEigenschaft - }); - } - } - ); - } - - #addSpecialAbilitiesToContext(context) { - context.specialAbilities = []; - const actorData = context.data; - Object.values(actorData.items).forEach((item) => { - if (item.type === "SpecialAbility") { - context.specialAbilities.push({ - id: item._id, - name: item.name, - }); - } - } - ); - } - - #findEquipmentOnSlot(slot, setNumber) { - return this.object.items.get(this.object.system.heldenausruestung[setNumber]?.[slot]) - } - - #addActionsToContext(context) { - const am = new ActionManager(this.object) - context.actions = am.evaluate() - } - - #isWorn(itemId) { - - const slots = PlayerCharacterDataModel.getSlots() - const set = this.object.system.heldenausruestung[this.object.system.setEquipped] - if (set) { - for (const slot of slots) { - const equipmentSlotId = set[slot] - if (equipmentSlotId === itemId) { - return slot - } - } - } - - return false - } - - async #addCombatStatistics(context) { - const actorData = context.data; - - context.inidice = actorData.system.ini.wuerfel; - context.inivalue = actorData.system.ini.aktuell; - context.inimod = actorData.system.ini.mod; - - context.aupper = Math.min((context.actor.system.aup.aktuell / context.actor.system.aup.max) * 100, 100); - context.lepper = Math.min((context.actor.system.lep.aktuell / context.actor.system.lep.max) * 100, 100); - context.keper = Math.min((context.actor.system.kap.aktuell / context.actor.system.kap.max) * 100, 100); - context.aspper = Math.min((context.actor.system.asp.aktuell / context.actor.system.asp.max) * 100, 100); - context.lepcurrent = context.actor.system.lep.aktuell ?? 0 - - context.aupcurrent = context.actor.system.aup.aktuell ?? 0 - - const fernkampf = this.#findEquipmentOnSlot("fernkampf", context.actor.system.setEquipped) - const links = this.#findEquipmentOnSlot("links", context.actor.system.setEquipped) - const rechts = this.#findEquipmentOnSlot("rechts", context.actor.system.setEquipped) - context.attacks = []; - - if (fernkampf) { - const fkitems = fernkampf.system.rangedSkills.map(async (skillInQuestion) => await this.object.items.getName(skillInQuestion)) - fkitems.forEach(async skill => { - const obj = await skill - context.attacks.push({ - name: obj.name, - using: fernkampf.name, - atroll: `1d20cs<${this.object.system.fk.aktuell + obj.system.at}`, - at: `${this.object.system.fk.aktuell + obj.system.at}`, - tproll: `${fernkampf.system.rangedAttackDamage}`, // TODO consider adding TP/KK mod and Range mod - tp: `${fernkampf.system.rangedAttackDamage}`, - iniroll: `(${context.inidice})d6 + ${context.inivalue + fernkampf.system.iniModifier ?? 0}`, - ini: `${context.inidice}w6 + ${context.inivalue + fernkampf.system.iniModifier ?? 0}`, - }) - }) - } - if (links) { - const meitems = links.system.meleeSkills.map(async (skillInQuestion) => await this.object.items.getName(skillInQuestion)) - meitems.forEach(async skill => { - const obj = await skill - context.attacks.push({ - name: obj.name, - using: links.name, - atroll: `1d20cs<${this.object.system.at.links.aktuell + obj.system.at + links.system.attackModifier}`, // TODO consider adding W/M - at: `${this.object.system.at.links.aktuell + obj.system.at + links.system.attackModifier}`, - paroll: `1d20cs<${this.object.system.pa.links.aktuell + obj.system.pa + links.system.parryModifier}`, // TODO consider adding W/M - pa: `${this.object.system.pa.links.aktuell + obj.system.pa + links.system.parryModifier}`, - tproll: `${links.system.meleeAttackDamage}`, // TODO consider adding TP/KK mod - tp: `${links.system.meleeAttackDamage}`, - iniroll: `(${context.inidice})d6 + ${context.inivalue + links.system.iniModifier ?? 0}`, - ini: `${context.inidice}w6 + ${context.inivalue + links.system.iniModifier ?? 0}`, - }) - }) - } - if (rechts) { - const meitems = rechts.system.meleeSkills.map(async (skillInQuestion) => await this.object.items.getName(skillInQuestion)) - meitems.forEach(async skill => { - const obj = await skill - console.log(this.object.system.at) - context.attacks.push({ - name: obj.name, - using: rechts.name, - atroll: `1d20cs<${this.object.system.at.rechts.aktuell + obj.system.at + rechts.system.attackModifier}`, // TODO consider adding W/M - at: `${this.object.system.at.rechts.aktuell + obj.system.at + rechts.system.attackModifier}`, - paroll: `1d20cs<${this.object.system.pa.rechts.aktuell + obj.system.pa + rechts.system.parryModifier}`, // TODO consider adding W/M - pa: `${this.object.system.pa.rechts.aktuell + obj.system.pa + rechts.system.parryModifier}`, - tproll: `${rechts.system.meleeAttackDamage}`, // TODO consider adding TP/KK mod - tp: `${rechts.system.meleeAttackDamage}`, - iniroll: `(${context.inidice})d6 + ${context.inivalue + rechts.system.iniModifier ?? 0}`, - ini: `${context.inidice}w6 + ${context.inivalue + rechts.system.iniModifier ?? 0}`, - }) - }) - } - - // add weapons to sidebar - } - - prepareEigenschaftRoll(actorData, name) { - if (name && name !== "*") { - return actorData.system.attribute[name.toLowerCase()].aktuell - } else { - return 0 - } - } - - #addEquipmentsToContext(context) { - context.equipments = []; - const actorData = context.data; - context.carryingweight = 0; - Object.values(actorData.items).forEach((item, index) => { - if (item.type === "Equipment") { - - // worn items are halved weight - - let effectiveWeight = item.system.weight ?? 0 - if (this.#isWorn(item._id)) { - effectiveWeight = item.system.weight ? item.system.weight / 2 : 0 - } - - context.equipments.push({ - index: index, - id: item._id, - quantity: item.system.quantity, - name: item.name, - icon: item.img ?? "", - weight: item.system.weight, - worn: this.#isWorn(item._id) - }) - context.carryingweight += item.system.quantity * effectiveWeight; - } - }) - context.maxcarryingcapacity = actorData.system.attribute.kk.aktuell - context.carryingpercentage = Math.min((context.carryingweight / context.maxcarryingcapacity) * 100, 100); - - const maxSets = 3 - const romanNumerals = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"] - context.sets = [] - for (let setIndex = 0; setIndex < maxSets; setIndex++) { - - context.sets.push({ - tab: "set" + (setIndex + 1), - name: romanNumerals[setIndex], - index: setIndex, - slots: [ - { - target: "links", - id: this.object.system.heldenausruestung[setIndex]?.links, - name: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.links)?.name, - icon: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.links)?.img - }, - { - target: "rechts", - id: this.object.system.heldenausruestung[setIndex]?.rechts, - name: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.rechts)?.name, - icon: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.rechts)?.img - }, - { - target: "brust", - id: this.object.system.heldenausruestung[setIndex]?.brust, - name: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.brust)?.name, - icon: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.brust)?.img - }, - { - target: "ruecken", - id: this.object.system.heldenausruestung[setIndex]?.ruecken, - name: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.ruecken)?.name, - icon: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.ruecken)?.img - }, - { - target: "kopf", - id: this.object.system.heldenausruestung[setIndex]?.kopf, - name: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.kopf)?.name, - icon: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.kopf)?.img - }, - { - target: "fernkampf", - id: this.object.system.heldenausruestung[setIndex]?.fernkampf, - name: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.fernkampf)?.name, - icon: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.fernkampf)?.img - }, - { - target: "munition", - id: this.object.system.heldenausruestung[setIndex]?.munition, - name: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.munition)?.name, - icon: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.munition)?.img - }, - { - target: "armlinks", - id: this.object.system.heldenausruestung[setIndex]?.armlinks, - name: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.armlinks)?.name, - icon: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.armlinks)?.img - }, - { - target: "armrechts", - id: this.object.system.heldenausruestung[setIndex]?.armrechts, - name: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.armrechts)?.name, - icon: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.armrechts)?.img - }, - { - target: "bauch", - id: this.object.system.heldenausruestung[setIndex]?.bauch, - name: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.bauch)?.name, - icon: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.bauch)?.img - }, - { - target: "beinlinks", - id: this.object.system.heldenausruestung[setIndex]?.beinlinks, - name: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.beinlinks)?.name, - icon: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.beinlinks)?.img - }, - { - target: "beinrechts", - id: this.object.system.heldenausruestung[setIndex]?.beinrechts, - name: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.beinrechts)?.name, - icon: this.object.items.get(actorData.system.heldenausruestung[setIndex]?.beinrechts)?.img - } - ] - }) - } - } - - async _onTalentRoll(event) { - event.preventDefault(); - const dataset = event.currentTarget.dataset; - console.log(dataset) - if (dataset.rolleigenschaft1) { - 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: [dataset.rolleigenschaft1, dataset.rolleigenschaft2, dataset.rolleigenschaft3], - }) - - 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, - } - } - - _onAttributeRoll(event) { - event.preventDefault(); - const dataset = event.currentTarget.dataset; - if (dataset.roll) { - let label = dataset.label ? `[Attribut] ${dataset.label}` : ''; - let roll = new Roll(dataset.roll, this.actor.getRollData()); - roll.toMessage({ - speaker: ChatMessage.getSpeaker({actor: this.actor}), - flavor: label, - rollMode: game.settings.get('core', 'rollMode'), - }); - return roll; - } - } - - openEmbeddedDocument(documentId) { - this.object.items.get(documentId).sheet.render(true) - } - - _onRoll(event) { - event.preventDefault(); - const dataset = event.currentTarget.dataset; - if (dataset.roll) { - let label = dataset.label ? `${dataset.label}` : ''; - let roll = new Roll(dataset.roll, this.actor.getRollData()); - roll.toMessage({ - speaker: ChatMessage.getSpeaker({actor: this.actor}), - flavor: label, - rollMode: game.settings.get('core', 'rollMode'), - }); - return roll; - } - } - - #mapAllSets() { - const updateObject = {} - Array.from(this.object.system.heldenausruestung).forEach((equipmentSet, index) => { - updateObject[`system.heldenausruestung.${index}.links`] = equipmentSet.links; - updateObject[`system.heldenausruestung.${index}.rechts`] = equipmentSet.rechts; - updateObject[`system.heldenausruestung.${index}.brust`] = equipmentSet.brust; - updateObject[`system.heldenausruestung.${index}.bauch`] = equipmentSet.bauch; - updateObject[`system.heldenausruestung.${index}.ruecken`] = equipmentSet.ruecken; - updateObject[`system.heldenausruestung.${index}.kopf`] = equipmentSet.kopf; - updateObject[`system.heldenausruestung.${index}.fernkampf`] = equipmentSet.fernkampf; - updateObject[`system.heldenausruestung.${index}.munition`] = equipmentSet.munition; - updateObject[`system.heldenausruestung.${index}.armlinks`] = equipmentSet.armlinks; - updateObject[`system.heldenausruestung.${index}.armrechts`] = equipmentSet.armrechts; - updateObject[`system.heldenausruestung.${index}.beinlinks`] = equipmentSet.beinlinks; - updateObject[`system.heldenausruestung.${index}.beinrechts`] = equipmentSet.beinrechts; - - }) - return updateObject; - } - - showAdjustAttributeDialog(attributeName, attributeField, previousValue) { - const thisActor = this; - const myContent = ` - Value: - - `; - - function updateAttribute(html) { - const value = html.find("input#attributeValue").val(); - const attribute = {} - attribute[attributeField.toLowerCase()] = { - aktuell: value - } - thisActor.object.update({system: {attribute}}) - } - - new Dialog({ - title: `${attributeName} ändern auf`, - content: myContent, - buttons: { - button1: { - label: "Ändern", - callback: (html) => { - updateAttribute(html) - }, - icon: `` - } - } - }).render(true); - - } - - #addLiturgiesToContext(context) { - const actorData = context.data; - context.liturgies = []; - context.blessings = []; - - Object.values(actorData.items).forEach((item, index) => { - if (item.type === "Blessing") { - context.blessings.push({ - deity: item.system.gottheit, - value: item.system.wert - }) - } - }) - Object.values(actorData.items).forEach((item, index) => { - if (item.type === "Liturgy") { - - context.blessings.forEach(({deity, value}) => { - let insertObject = context.liturgies.find(p => p.deity === deity); - if (!insertObject) { - insertObject = { - deity: deity, - lkp: value, - O: [], - I: [], - II: [], - III: [], - IV: [], - V: [], - VI: [], - VII: [], - VIII: [], - "NA": [], - countO: 1, - countI: 1, - countII: 1, - countIII: 1, - countIV: 1, - countV: 1, - countVI: 1, - countVII: 1, - countVIII: 1, - countNA: 0, - total: 3, - - } - context.liturgies.push(insertObject); - } - - // sort by rank - const rankData = LiturgyData.getRankOfLiturgy(item.system, deity) - if (rankData) { - let {index, name, lkp, mod, costKaP} = rankData; - - insertObject["count" + name] = insertObject["count" + name] + 1; - - insertObject[name].push({ - id: item._id, - name: item.name, - lkpReq: lkp, - lkpMod: mod, - costKaP, - rank: index, // get effective liturgy rank based on deity - liturgiekenntnis: deity, - }) - insertObject.total = insertObject.total + 2; - - } - }) - } - }) - - - // clean up counter - Object.values(context.liturgies).forEach((litObject) => { - - if (litObject.I.length === 0) litObject.countI = false; - if (litObject.II.length === 0) litObject.countII = false; - if (litObject.III.length === 0) litObject.countIII = false; - if (litObject.IV.length === 0) litObject.countIV = false; - if (litObject.V.length === 0) litObject.countV = false; - if (litObject.VI.length === 0) litObject.countVI = false; - if (litObject.VII.length === 0) litObject.countVII = false; - if (litObject.VIII.length === 0) litObject.countVIII = false; - if (litObject.NA.length === 0) litObject.countNA = false; - - - }) - - context.hasLiturgies = context.blessings.length > 0; - } - - #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; - } - } - } - - async #handleDroppedActiveEffect(actor, activeEffect) { - const array = Array.from(actor.items); - for (let i = 0; i < array.length; i++) { - if (array[i].name === activeEffect.name) { - // replace active effect if its unique - - return true; - } - } - } - - #handleDroppedAdvantage(actor, advantage) { - const array = Array.from(actor.items); - for (let i = 0; i < array.length; i++) { - if (array[i].name === advantage.name) { // TODO: adjust for uniqueness - return false; - } - } - } - - activateListeners(html) { - super.activateListeners(html); - - const tabs = new foundry.applications.ux.Tabs({ - navSelector: ".paperdoll-tabs.tabs", - contentSelector: ".sheet-body.paperdoll-sets", - initial: "set" + (this.object.system.setEquipped + 1) - }); - tabs.bind(html[0]); - - html.on('click', '.attribute.rollable', (evt) => { - this._onAttributeRoll(evt); - }); - - html.on('click', '[data-operation="switchSet"]', (evt) => { - const {id} = evt.currentTarget.dataset; - console.log(id); - this.object.update({"system.setEquipped": id}) - }) - - html.on('click', '[data-operation="removeEffect"]', (evt) => { - const {actorId, effectId} = evt.currentTarget.dataset; - if (game.user.isGM) { - this.object.items.get(effectId).delete(); - } - }) - - html.on('click', '.talent.rollable', (evt) => { - this._onTalentRoll(evt); - }); - - html.on('click', '.sidebar-element.rollable', (evt) => { - this._onRoll(evt); - }); - - // TODO: merge into click.clickable handler - html.on('click', '.talent .name', (evt) => { - this.openEmbeddedDocument(evt.target.dataset.id); - evt.stopPropagation(); - }) - - // TODO: merge into click.clickable handler - html.on('click', '.advantage .name', (evt) => { - this.openEmbeddedDocument(evt.target.dataset.id); - evt.stopPropagation(); - }) - - // TODO: merge into click.clickable handler - html.on('click', '.equipment', (evt) => { - this.openEmbeddedDocument(evt.target.parentElement.dataset.id); - evt.stopPropagation(); - }) - - html.on('click', '.clickable', async (evt) => { - const {id, operation} = evt.currentTarget.dataset; - if (operation === "openActorSheet") { - this.openEmbeddedDocument(id); - evt.stopPropagation(); - } - }) - /* - html.on('dragstart', '.equipment', (evt) => { - evt.originalEvent.dataTransfer.setData("application/json", JSON.stringify({ - documentId: evt.currentTarget.dataset.id - })); - })*/ - /* - html.on('drop', '.equipped', async (evt) => { - const {actor, target, setId} = evt.currentTarget.dataset; - try { - const {documentId} = JSON.parse(evt.originalEvent.dataTransfer.getData("application/json")); - - - if (actor === this.object._id && documentId) { // managing equipped items - //const slot = this.#isWorn(documentId, setId) - //const updateObject = await this.#getEquipmentset(Number(setId)) - const updateObject = this.#mapAllSets() - updateObject[`system.heldenausruestung.${setId}.${target}`] = documentId; - console.log(updateObject); - - await this.object.update(updateObject); - } - - evt.stopPropagation(); - } catch (e) { - } - })*/ - - new foundry.applications.ux.ContextMenu(html[0], '.talent.rollable', [ - { - name: "Entfernen", - icon: '', - callback: (event) => { - this.object.deleteEmbeddedDocuments('Item', [event[0].dataset.id]) - }, - condition: () => true - } - ], { - jQuery: false - }); - - - new foundry.applications.ux.ContextMenu(html[0], '.attribute.rollable', [ - { - name: "Anpassen", - icon: '', - callback: (event) => { - this.showAdjustAttributeDialog(event[0].dataset.name, event[0].dataset.label, event[0].dataset.value) - }, - condition: () => true - } - ], { - jQuery: false - }); - - let handler = evt => { - const talentId = evt.target.dataset.id - evt.dataTransfer.setData("application/json", JSON.stringify({ - talentId - })); - this._onDragStart(evt) - - } - - // 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); - }); - - new foundry.applications.ux.ContextMenu(html[0], '.equipment', [ - { - name: "Aus dem Inventar entfernen", - icon: '', - callback: (event) => { - // TODO find id on heldenausruestung to remove the worn items as well - this.object.deleteEmbeddedDocuments('Item', [event[0].dataset.id]) - }, - condition: () => true - } - ], { - jQuery: false - }); - - new foundry.applications.ux.ContextMenu(html[0], '.equipped', [ - { - name: "Gegenstand vom Set entfernen", - callback: (event) => { - const {setId, target, actor} = event[0].dataset - - const updateObject = this.#mapAllSets() - updateObject[`system.heldenausruestung.${setId}.${target}`] = null; - - this.object.update(updateObject); - }, - condition: () => true - } - ], { - jQuery: false - }); - - html.on('click', '[data-operation="addWounds"]', async (evt) => { - const {value} = evt.currentTarget.dataset - this.object.update({"system.wunden.aktuell": value}) - }) - - html.on('click', '[data-operation="reduceWounds"]', async (evt) => { - const {value} = evt.currentTarget.dataset - this.object.update({"system.wunden.aktuell": value}) - }) - - html.on('click', '.liturgy.rollable', async (evt) => { - - evt.stopPropagation(); - - const {id, rank, lkp, deity} = evt.currentTarget.dataset; - const document = await this.object.items.get(id) - - const data = {}; - - data.rank = rank; - data.lkp = lkp; - data.deity = deity; - data.variations = []; - const ranks = LiturgyData.ranks - ranks.forEach(rank => { - if (document.system.auswirkung[rank]) { - data.variations.push({ - rank, - effect: document.system.auswirkung[rank] - }) - } - }) - data.mods = []; - - const htmlContent = await renderTemplate('systems/DSA_4-1/templates/dialog/modify-liturgy.hbs', data); - - const dialogData = { - title: document.name, - content: htmlContent, - data: {}, + new Dialog({ + title: `${attributeName} ändern auf`, + content: myContent, buttons: { - submit: { - label: "Wirken", - icon: '', + button1: { + label: "Ändern", callback: (html) => { + updateAttribute(html) + }, + icon: `` + } + } + }).render(true); + + }*/ + + /* + activateListeners(html) { + super.activateListeners(html); + + const tabs = new foundry.applications.ux.Tabs({ + navSelector: ".paperdoll-tabs.tabs", + contentSelector: ".sheet-body.paperdoll-sets", + initial: "set" + (this.object.system.setEquipped + 1) + }); + tabs.bind(html[0]); + + html.on('click', '.attribute.rollable', (evt) => { + this._onAttributeRoll(evt); + }); + + html.on('click', '[data-operation="switchSet"]', (evt) => { + const {id} = evt.currentTarget.dataset; + console.log(id); + this.object.update({"system.setEquipped": id}) + }) + + html.on('click', '[data-operation="removeEffect"]', (evt) => { + const {actorId, effectId} = evt.currentTarget.dataset; + if (game.user.isGM) { + this.object.items.get(effectId).delete(); + } + }) + + html.on('click', '.talent.rollable', (evt) => { + this._onTalentRoll(evt); + }); + + html.on('click', '.sidebar-element.rollable', (evt) => { + this._onRoll(evt); + }); + + // TODO: merge into click.clickable handler + html.on('click', '.talent .name', (evt) => { + this.openEmbeddedDocument(evt.target.dataset.id); + evt.stopPropagation(); + }) + + // TODO: merge into click.clickable handler + html.on('click', '.advantage .name', (evt) => { + this.openEmbeddedDocument(evt.target.dataset.id); + evt.stopPropagation(); + }) + + // TODO: merge into click.clickable handler + html.on('click', '.equipment', (evt) => { + this.openEmbeddedDocument(evt.target.parentElement.dataset.id); + evt.stopPropagation(); + }) + + html.on('click', '.clickable', async (evt) => { + const {id, operation} = evt.currentTarget.dataset; + if (operation === "openActorSheet") { + this.openEmbeddedDocument(id); + evt.stopPropagation(); + } + }) + + new foundry.applications.ux.ContextMenu(html[0], '.talent.rollable', [ + { + name: "Entfernen", + icon: '', + callback: (event) => { + this.object.deleteEmbeddedDocuments('Item', [event[0].dataset.id]) + }, + condition: () => true + } + ], { + jQuery: false + }); + + + new foundry.applications.ux.ContextMenu(html[0], '.attribute.rollable', [ + { + name: "Anpassen", + icon: '', + callback: (event) => { + this.showAdjustAttributeDialog(event[0].dataset.name, event[0].dataset.label, event[0].dataset.value) + }, + condition: () => true + } + ], { + jQuery: false + }); + + let handler = evt => { + const talentId = evt.target.dataset.id + evt.dataTransfer.setData("application/json", JSON.stringify({ + talentId + })); + this._onDragStart(evt) + } + + // 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); + }); + + html.on('click', '[data-operation="addWounds"]', async (evt) => { + const {value} = evt.currentTarget.dataset + this.object.update({"system.wunden.aktuell": value}) + }) + + html.on('click', '[data-operation="reduceWounds"]', async (evt) => { + const {value} = evt.currentTarget.dataset + this.object.update({"system.wunden.aktuell": value}) + }) + + html.on('click', '.liturgy.rollable', async (evt) => { + + evt.stopPropagation(); + + const {id, rank, lkp, deity} = evt.currentTarget.dataset; + const document = await this.object.items.get(id) + + const data = {}; + + data.rank = rank; + data.lkp = lkp; + data.deity = deity; + data.variations = []; + const ranks = LiturgyData.ranks + ranks.forEach(rank => { + if (document.system.auswirkung[rank]) { + data.variations.push({ + rank, + effect: document.system.auswirkung[rank] + }) + } + }) + data.mods = []; + + const htmlContent = await renderTemplate('systems/DSA_4-1/templates/dialog/modify-liturgy.hbs', data); + + const dialogData = { + title: document.name, + content: htmlContent, + data: {}, + buttons: { + submit: { + label: "Wirken", + icon: '', + callback: (html) => { + }, }, }, - }, - } - dialogData.render = new ModifyLiturgy(data).handleRender + } + dialogData.render = new ModifyLiturgy(data).handleRender - const dialog = new Dialog(dialogData, { - classes: ['dsa41', 'dialog', 'liturgy'], - height: 480 + const dialog = new Dialog(dialogData, { + classes: ['dsa41', 'dialog', 'liturgy'], + height: 480 + }) + + dialog.render(true); + + return false; }) - dialog.render(true); - return false; - }) - - - } - - #handleDroppedEquipment(actor, equipment) { - const array = Array.from(actor.items); - for (let i = 0; i < array.length; i++) { - if (array[i].name === equipment.name) { // TODO: adjust item quantity if item is the same - return false; - } } - } - - #handleDroppedLiturgy(actor, liturgy) { - const array = Array.from(actor.items); - for (let i = 0; i < array.length; i++) { - if (array[i].name === liturgy.name) { // TODO: allow multiple miracles with the same name - return false; - } - } - } - - #handleDroppedSpecialAbility(actor, specialAbility) { - const array = Array.from(actor.items); - for (let i = 0; i < array.length; i++) { - if (array[i].name === specialAbility.name) { // TODO: allow multiple miracles with the same name - return false; - } - } - } - + */ } + +export default CharacterSheet diff --git a/src/module/sheets/groupSheet.mjs b/src/module/sheets/groupSheet.mjs index 58ba836a..b3ed1427 100644 --- a/src/module/sheets/groupSheet.mjs +++ b/src/module/sheets/groupSheet.mjs @@ -75,21 +75,6 @@ export class GroupSheet extends HandlebarsApplicationMixin(ActorSheetV2) { 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), - drop: this._onDrop.bind(this) - } - return new DragDrop(d) - }) - } - #stringToKeyFieldName(s) { return s } diff --git a/src/templates/actor/actor-character-sheet.hbs b/src/templates/actor/actor-character-sheet.hbs deleted file mode 100644 index f499c11b..00000000 --- a/src/templates/actor/actor-character-sheet.hbs +++ /dev/null @@ -1,814 +0,0 @@ -
- - {{!-- Sheet Header --}} -
- {{!-- Header stuff goes here --}} -
-
- {{#each attributes}} - {{> "systems/DSA_4-1/templates/ui/partial-attribute-button.hbs" this}} - {{/each}} -
-
-
- -
-

- - - - - - {{#if ausdauer}} - - {{/if}} - - {{#if this.hasLiturgies}} - - {{/if}} - - {{#if this.hasSpells}} - - {{/if}} - - {{#each attacks}} -
-

{{this.using}} ({{this.name}})

-
- {{#if this.at}} - - {{/if}} - {{#if this.pa}} - - {{/if}} -
- {{#if this.at}} - - {{/if}} - {{#if this.ini}} - - {{/if}} -
- {{/each}} - - - -
- - {{!-- Sheet Tab Navigation --}} - - - {{!-- Sheet Body --}} -
-
- - - - -
-
-
-
- - -
- {{#each this.mods.mu}} - {{this.value}} - {{/each}} -
-
-
- - -
- {{#each this.mods.kl}} - {{this.value}} - {{/each}} -
-
-
- - -
- {{#each this.mods.in}} - {{this.value}} - {{/each}} -
- -
-
- - -
- {{#each this.mods.ch}} - {{this.value}} - {{/each}} -
- -
-
- - -
- {{#each this.mods.ff}} - {{this.value}} - {{/each}} -
- -
-
- - -
- {{#each this.mods.ge}} - {{this.value}} - {{/each}} -
- -
-
- - -
- {{#each this.mods.ko}} - {{this.value}} - {{/each}} -
- -
-
- - -
- {{#each this.mods.kk}} - {{this.value}} - {{/each}} -
- -
-
- - -
-
- - -
- {{#each this.mods.at}} - {{this.value}} - {{/each}} -
-
-
- - -
- {{#each this.mods.pa}} - {{this.value}} - {{/each}} -
-
-
- - -
- {{#each this.mods.fk}} - {{this.value}} - {{/each}} -
-
-
-
-
- - - -
- {{#if ausdauer}} -
- - - -
- {{/if}} - {{#if hasSpells}} -
- - - -
- {{/if}} - {{#if hasLiturgies}} -
- - - -
- {{/if}} -
-
-

Vor- und Nachteile

-
    - {{#each this.advantages}} -
  • {{> "systems/DSA_4-1/templates/ui/partial-advantage-button.hbs" this}}
  • - {{/each}} -
-
-
-

Sonderfertigkeiten

-
    - {{#each this.specialAbilities}} -
  • {{> "systems/DSA_4-1/templates/ui/partial-sf-button.hbs" this}}
  • - {{/each}} -
-
-
- -
- -
- -
- - - w6 - -
-
- - - von - -
- {{#if ausdauer}} -
- - - von - -
- {{/if}} - {{#if (not zonenruestung)}} -
- - {{derived.rs}} -
- {{/if}} -
- - {{derived.be}} -
- - -
- {{#if (not trefferzonen)}} -
- - {{#each this.woundsFilled}} - {{#if this}} -
{{@index}}
- {{else}} -
{{@index}}
- {{/if}} - {{/each}} -
- {{/if}} - - -
-

Aktionen im Kampf

- {{#each this.actions}} - {{> "systems/DSA_4-1/templates/ui/partial-action-button.hbs" this}} - {{/each}} -
- - {{#if (or trefferzonen zonenruestung)}} -
-

{{#if (and trefferzonen zonenruestung)}}Trefferzonen{{/if}}{{#if - (and trefferzonen (not zonenruestung))}}Wunden{{/if}}{{#if - (and (not trefferzonen) zonenruestung)}}Rüstung{{/if}}

-
- - - - {{#if trefferzonen}} - {{derived.wunden.kopf}} - {{derived.wunden.brust}} - {{derived.wunden.armlinks}} - {{derived.wunden.armrechts}} - {{derived.wunden.bauch}} - {{derived.wunden.beinlinks}} - {{derived.wunden.beinrechts}} - {{/if}} - {{#if zonenruestung}} - {{derived.rs.kopf}} - {{derived.rs.brust}} - {{derived.rs.armlinks}} - {{derived.rs.armrechts}} - {{derived.rs.bauch}} - {{derived.rs.beinlinks}} - {{derived.rs.beinrechts}} - {{/if}} -
-
- {{/if}} - -
-
-
-

Kampftalente

-
    - {{#each skills.Kampf}} -
  • - {{> "systems/DSA_4-1/templates/ui/partial-rollable-weaponskill-button.hbs" this}} -
  • - {{/each}} -
-
-
-

Körperliche Talente

-
    -
  • - {{#each skills.Körperlich}} -
  • - {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} -
  • - {{/each}} -
-
-
-

Gesellschaftliche Talente

-
    -
  • - {{#each skills.Gesellschaft}} -
  • - {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} -
  • - {{/each}} -
-
-
-

Natur Talente

-
    -
  • - {{#each skills.Natur}} -
  • - {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} -
  • - {{/each}} -
-
-
-

Wissenstalente

-
    -
  • - {{#each skills.Wissen}} -
  • - {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} -
  • - {{/each}} -
-
-
-

Schriften & Sprachen

-
    -
  • - {{#each skills.Schriften}} -
  • - {{> "systems/DSA_4-1/templates/ui/partial-rollable-language-button.hbs" this}} -
  • - {{/each}} - {{#each skills.Sprachen}} -
  • - {{> "systems/DSA_4-1/templates/ui/partial-rollable-language-button.hbs" this}} -
  • - {{/each}} -
-
-
-

Handwerkliche Talente

-
    -
  • - {{#each skills.Handwerk}} -
  • - {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} -
  • - {{/each}} -
-
- -
-
- -
- -
- -
-
- - -
-

Inventar

- - {{> "systems/DSA_4-1/templates/ui/partial-equipment-button.hbs" equipments}} - -
- -
-

Ausrüstung

- {{!-- Set Tab Navigation --}} - - {{!-- Set Body --}} -
- {{#each this.sets}} -
- -
- - - - - {{#each this.slots}} -
- {{/each}} - {{#if (eq ../actor.system.setEquipped @index)}} - - {{else}} - - {{/if}} - -
-
- {{/each}} - -
-
- -
- {{#if this.hasSpells}} -
- -
- -
- - - von - -
-
- - -
-
- - - - - - - - - - - - - {{#each this.spells}} - - - - - - - - - - {{/each}} - -
ZaubernameProbeZfWMerkmale
- {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} - - {{this.name}}{{this.eigenschaft1}}{{this.eigenschaft2}}{{this.eigenschaft3}}{{this.zfw}} -
    {{#each this.merkmal}} -
  • {{this}}
  • {{/each}}
-
- -
- {{/if}} - {{#if this.hasLiturgies}} -
- -
- -
- - - von - -
-
- - {{#each this.liturgies}} - - - - - - - - - - {{#if this.countO}} - - - - - {{#each this.O}} - - - - - - {{/each}} - {{/if}} - {{#if this.countI}} - - - - {{#each this.I}} - - - - - - {{/each}} - {{/if}} - {{#if this.countII}} - - - - {{#each this.II}} - - - - - {{/each}} - {{/if}} - {{#if this.countIII}} - - - - {{#each this.III}} - - - - - {{/each}} - {{/if}} - {{#if this.countIV}} - - - - {{#each this.IV}} - - - - - {{/each}}{{/if}} - {{#if this.countV}} - - - - {{#each this.V}} - - - - - {{/each}} - {{/if}} - {{#if this.countVI}} - - - - {{#each this.VI}} - - - - - {{/each}} - {{/if}}{{#if this.countVII}} - - - - {{#each this.VII}} - - - - - {{/each}} - {{/if}}{{#if this.countVIII}} - - - - {{#each this.VIII}} - - - - - {{/each}} - {{/if}} - -
Liturgiekenntnis: {{this.lkp}}
- {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} - - {{this.name}}
- {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} - - {{this.name}}
- {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} - {{this.name}}
- {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} - {{this.name}}
- {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} - {{this.name}}
- {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} - {{this.name}}
- {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} - {{this.name}}
- {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} - {{this.name}}
- {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} - {{this.name}}
- {{/each}} - -
- {{/if}} - -
- - - - - - - - {{#each this.effects}} - - - - - - {{/each}} - -
EffektVeränderungen
- {{this.name}} - {{this.conditions}}{{#if ../isGM}} - {{/if}}
-
- -
-
diff --git a/src/templates/actor/character/main-sheet.hbs b/src/templates/actor/character/main-sheet.hbs new file mode 100644 index 00000000..d034f3a8 --- /dev/null +++ b/src/templates/actor/character/main-sheet.hbs @@ -0,0 +1,91 @@ +
+ + {{!-- Sheet Header --}} +
+ {{!-- Header stuff goes here --}} +
+
+ {{#each attributes}} + {{> "systems/DSA_4-1/templates/ui/partial-attribute-button.hbs" this}} + {{/each}} +
+
+
+ +
+

+ + + + + + {{#if ausdauer}} + + {{/if}} + + {{#if this.hasLiturgies}} + + {{/if}} + + {{#if this.hasSpells}} + + {{/if}} + + {{#each attacks}} +
+

{{this.using}} ({{this.name}})

+
+ {{#if this.at}} + + {{/if}} + {{#if this.pa}} + + {{/if}} +
+ {{#if this.at}} + + {{/if}} + {{#if this.ini}} + + {{/if}} +
+ {{/each}} + + + +
+ + {{!-- Sheet Tab Navigation --}} + + +
diff --git a/src/templates/actor/character/tab-attributes.hbs b/src/templates/actor/character/tab-attributes.hbs new file mode 100644 index 00000000..842f2973 --- /dev/null +++ b/src/templates/actor/character/tab-attributes.hbs @@ -0,0 +1,161 @@ +
+ +
+
+ + +
+ {{#each this.mods.mu}} + {{this.value}} + {{/each}} +
+
+
+ + +
+ {{#each this.mods.kl}} + {{this.value}} + {{/each}} +
+
+
+ + +
+ {{#each this.mods.in}} + {{this.value}} + {{/each}} +
+ +
+
+ + +
+ {{#each this.mods.ch}} + {{this.value}} + {{/each}} +
+ +
+
+ + +
+ {{#each this.mods.ff}} + {{this.value}} + {{/each}} +
+ +
+
+ + +
+ {{#each this.mods.ge}} + {{this.value}} + {{/each}} +
+ +
+
+ + +
+ {{#each this.mods.ko}} + {{this.value}} + {{/each}} +
+ +
+
+ + +
+ {{#each this.mods.kk}} + {{this.value}} + {{/each}} +
+ +
+
+ + +
+
+ + +
+ {{#each this.mods.at}} + {{this.value}} + {{/each}} +
+
+
+ + +
+ {{#each this.mods.pa}} + {{this.value}} + {{/each}} +
+
+
+ + +
+ {{#each this.mods.fk}} + {{this.value}} + {{/each}} +
+
+
+
+
+ + + +
+ {{#if ausdauer}} +
+ + + +
+ {{/if}} + {{#if hasSpells}} +
+ + + +
+ {{/if}} + {{#if hasLiturgies}} +
+ + + +
+ {{/if}} +
+
+

Vor- und Nachteile

+
    + {{#each this.advantages}} +
  • {{> "systems/DSA_4-1/templates/ui/partial-advantage-button.hbs" this}}
  • + {{/each}} +
+
+
+

Sonderfertigkeiten

+
    + {{#each this.specialAbilities}} +
  • {{> "systems/DSA_4-1/templates/ui/partial-sf-button.hbs" this}}
  • + {{/each}} +
+
+ +
diff --git a/src/templates/actor/character/tab-combat.hbs b/src/templates/actor/character/tab-combat.hbs new file mode 100644 index 00000000..9992c484 --- /dev/null +++ b/src/templates/actor/character/tab-combat.hbs @@ -0,0 +1,100 @@ +
+ +
+ +
+ + + w6 + +
+
+ + + von + +
+ {{#if ausdauer}} +
+ + + von + +
+ {{/if}} + {{#if (not zonenruestung)}} +
+ + {{derived.rs}} +
+ {{/if}} +
+ + {{derived.be}} +
+ + +
+ {{#if (not trefferzonen)}} +
+ + {{#each this.woundsFilled}} + {{#if this}} +
{{@index}}
+ {{else}} +
{{@index}}
+ {{/if}} + {{/each}} +
+ {{/if}} + + +
+

Aktionen im Kampf

+ {{#each this.actions}} + {{> "systems/DSA_4-1/templates/ui/partial-action-button.hbs" this}} + {{/each}} +
+ + {{#if (or trefferzonen zonenruestung)}} +
+

{{#if (and trefferzonen zonenruestung)}}Trefferzonen{{/if}}{{#if + (and trefferzonen (not zonenruestung))}}Wunden{{/if}}{{#if + (and (not trefferzonen) zonenruestung)}}Rüstung{{/if}}

+
+ + + + {{#if trefferzonen}} + {{derived.wunden.kopf}} + {{derived.wunden.brust}} + {{derived.wunden.armlinks}} + {{derived.wunden.armrechts}} + {{derived.wunden.bauch}} + {{derived.wunden.beinlinks}} + {{derived.wunden.beinrechts}} + {{/if}} + {{#if zonenruestung}} + {{derived.rs.kopf}} + {{derived.rs.brust}} + {{derived.rs.armlinks}} + {{derived.rs.armrechts}} + {{derived.rs.bauch}} + {{derived.rs.beinlinks}} + {{derived.rs.beinrechts}} + {{/if}} +
+
+ {{/if}} + + + +
diff --git a/src/templates/actor/character/tab-effects.hbs b/src/templates/actor/character/tab-effects.hbs new file mode 100644 index 00000000..ca174837 --- /dev/null +++ b/src/templates/actor/character/tab-effects.hbs @@ -0,0 +1,27 @@ +
+ + + + + + + + + + + {{#each this.effects}} + + + + + + {{/each}} + +
EffektVeränderungen
+ {{this.name}} + {{this.conditions}}{{#if ../isGM}} + {{/if}}
+
\ No newline at end of file diff --git a/src/templates/actor/character/tab-equipment.hbs b/src/templates/actor/character/tab-equipment.hbs new file mode 100644 index 00000000..526254f3 --- /dev/null +++ b/src/templates/actor/character/tab-equipment.hbs @@ -0,0 +1,85 @@ +
+
+

Kampftalente

+
    + {{#each skills.Kampf}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-weaponskill-button.hbs" this}} +
  • + {{/each}} +
+
+
+

Körperliche Talente

+
    +
  • + {{#each skills.Körperlich}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
+

Gesellschaftliche Talente

+
    +
  • + {{#each skills.Gesellschaft}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
+

Natur Talente

+
    +
  • + {{#each skills.Natur}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
+

Wissenstalente

+
    +
  • + {{#each skills.Wissen}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
+

Schriften & Sprachen

+
    +
  • + {{#each skills.Schriften}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-language-button.hbs" this}} +
  • + {{/each}} + {{#each skills.Sprachen}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-language-button.hbs" this}} +
  • + {{/each}} +
+
+
+

Handwerkliche Talente

+
    +
  • + {{#each skills.Handwerk}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
\ No newline at end of file diff --git a/src/templates/actor/character/tab-liturgies.hbs b/src/templates/actor/character/tab-liturgies.hbs new file mode 100644 index 00000000..886f41bd --- /dev/null +++ b/src/templates/actor/character/tab-liturgies.hbs @@ -0,0 +1,202 @@ +
+ +
+ +
+ + + von + +
+
+ + {{#each this.liturgies}} + + + + + + + + + + {{#if this.countO}} + + + + + {{#each this.O}} + + + + + + {{/each}} + {{/if}} + {{#if this.countI}} + + + + {{#each this.I}} + + + + + + {{/each}} + {{/if}} + {{#if this.countII}} + + + + {{#each this.II}} + + + + + {{/each}} + {{/if}} + {{#if this.countIII}} + + + + {{#each this.III}} + + + + + {{/each}} + {{/if}} + {{#if this.countIV}} + + + + {{#each this.IV}} + + + + + {{/each}}{{/if}} + {{#if this.countV}} + + + + {{#each this.V}} + + + + + {{/each}} + {{/if}} + {{#if this.countVI}} + + + + {{#each this.VI}} + + + + + {{/each}} + {{/if}}{{#if this.countVII}} + + + + {{#each this.VII}} + + + + + {{/each}} + {{/if}}{{#if this.countVIII}} + + + + {{#each this.VIII}} + + + + + {{/each}} + {{/if}} + +
Liturgiekenntnis: {{this.lkp}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + {{this.name}}
+ {{/each}} + + +
\ No newline at end of file diff --git a/src/templates/actor/character/tab-meta.hbs b/src/templates/actor/character/tab-meta.hbs new file mode 100644 index 00000000..324470dc --- /dev/null +++ b/src/templates/actor/character/tab-meta.hbs @@ -0,0 +1,49 @@ +
+ + + +
\ No newline at end of file diff --git a/src/templates/actor/character/tab-skills.hbs b/src/templates/actor/character/tab-skills.hbs new file mode 100644 index 00000000..526254f3 --- /dev/null +++ b/src/templates/actor/character/tab-skills.hbs @@ -0,0 +1,85 @@ +
+
+

Kampftalente

+
    + {{#each skills.Kampf}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-weaponskill-button.hbs" this}} +
  • + {{/each}} +
+
+
+

Körperliche Talente

+
    +
  • + {{#each skills.Körperlich}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
+

Gesellschaftliche Talente

+
    +
  • + {{#each skills.Gesellschaft}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
+

Natur Talente

+
    +
  • + {{#each skills.Natur}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
+

Wissenstalente

+
    +
  • + {{#each skills.Wissen}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
+

Schriften & Sprachen

+
    +
  • + {{#each skills.Schriften}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-language-button.hbs" this}} +
  • + {{/each}} + {{#each skills.Sprachen}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-language-button.hbs" this}} +
  • + {{/each}} +
+
+
+

Handwerkliche Talente

+
    +
  • + {{#each skills.Handwerk}} +
  • + {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}} +
  • + {{/each}} +
+
+
\ No newline at end of file diff --git a/src/templates/actor/character/tab-spells.hbs b/src/templates/actor/character/tab-spells.hbs new file mode 100644 index 00000000..ed6cda06 --- /dev/null +++ b/src/templates/actor/character/tab-spells.hbs @@ -0,0 +1,49 @@ +
+ +
+ +
+ + + von + +
+
+ + +
+
+ + + + + + + + + + + + + {{#each this.spells}} + + + + + + + + + + {{/each}} + +
ZaubernameProbeZfWMerkmale
+ {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} + + {{this.name}}{{this.eigenschaft1}}{{this.eigenschaft2}}{{this.eigenschaft3}}{{this.zfw}} +
    {{#each this.merkmal}} +
  • {{this}}
  • {{/each}}
+
+
\ No newline at end of file