From bd9e20d9627ba5f35b8f3be22bb7a780cf0b6b7d Mon Sep 17 00:00:00 2001 From: macniel Date: Thu, 9 Oct 2025 17:54:46 +0200 Subject: [PATCH] adds styling to charactersheet, adds rudimentary activeffects management and handles armor value and handicaps based on equipped set and its equipped items --- src/assets/gradient.png | Bin 0 -> 500 bytes src/assets/velvet_button.png | Bin 0 -> 1275 bytes src/main.mjs | 22 ++- src/module/data/activeeffect.mjs | 49 +++++++ src/module/data/character.mjs | 7 +- src/module/data/specialAbility.mjs | 12 ++ src/module/documents/character.mjs | 40 +++++- src/module/documents/specialAbility.mjs | 9 ++ src/module/sheets/ActiveEffectSheet.mjs | 44 ++++++ src/module/sheets/characterSheet.mjs | 136 ++++++++++++++---- src/module/sheets/specialAbilitySheet.mjs | 49 +++++++ src/style/_active-effect-sheet.scss | 38 +++++ src/style/_character-sheet.scss | 125 ++++++++++++++++ src/style/styles.scss | 1 + src/system.json | 8 ++ src/templates/actor/actor-character-sheet.hbs | 136 +++++++++++++++++- .../item/item-activeeffect-sheet.hbs | 20 +++ src/templates/ui/partial-equipment-button.hbs | 2 +- src/templates/ui/partial-sf-button.hbs | 3 + 19 files changed, 662 insertions(+), 39 deletions(-) create mode 100644 src/assets/gradient.png create mode 100644 src/assets/velvet_button.png create mode 100644 src/module/data/activeeffect.mjs create mode 100644 src/module/data/specialAbility.mjs create mode 100644 src/module/documents/specialAbility.mjs create mode 100644 src/module/sheets/ActiveEffectSheet.mjs create mode 100644 src/module/sheets/specialAbilitySheet.mjs create mode 100644 src/style/_active-effect-sheet.scss create mode 100644 src/templates/item/item-activeeffect-sheet.hbs create mode 100644 src/templates/ui/partial-sf-button.hbs diff --git a/src/assets/gradient.png b/src/assets/gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..0ef0f8613da07a637e35112c78b6a3a53d143922 GIT binary patch literal 500 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSoCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&3=E8oo-U3d6?5L++{oMPAmHkF z+lnb@-G4X51F1P5(zJFwc$qDD|Fg|~{>be2wtv~!I2HUD3Yj{D9p*4RViDNB?)9uX z=4Krb?^>bE<@|&T`M(&?M7@6l?tX u-tpDu{1<77E$@EM0|pb+rKmypo!whsp(X3zt|!14WAJqKb6Mw<&;$Sn4x0Dw{owAT3k{)Tf7tu-j6kaLE$7W=-# z7=v|PQEQd=*XtD@A0JRkp|ys2p7Htl31bX?e`>9;)?)C__8$9bvs;+~nY&%eSQz7-OK6 z`t#CSXst0#lPt!j8Y0h2;yFxb7HV_PR3DnjA=1O?E8*V3Sx}1(ZN5LZ?)ElF&^ASDFv-H zq?8V^g)WM!T-Oz)6r_}pQo=M%2jji>*tSg)8oD;EwWxod=fOXbZ|N3NN@%U2wRT8M zxELq(D%Dy;YmIH&BvGO9{NFhzZih;xdkP`odc6+*iG2I@^(6@iVN?g7t+k>aV~n__ z-|p&nX+t+uN|8A+M#*-KF&O-F`Id1`@UnI=f7f7Uz*Txx*)<@Ysfjv7(VBmG5F{5&C}D<8yf`H zT2Y}=3YW_T_xt@&Y7nfomc(V6CUGnL_TEdZ>Ejs75^|`{!9Rzut+kR__D1z}q_q~0 zkB{J3=iDLV)LKh|LDhy3M0M6$EXx7_n5IeG6Ppr)e;!}6JlOXgIp;%N$`&I4yuZJT z!X6$T4zVPJAj)Lc>72vmauHVsK-!kfMElOw;Ge|bwoR00t;P5EH>PPqYYmsn1tA29 zBOF6@dhaC$g%D&O;|$lLd*g=Lh)_yl@XzIIYptk^r37OQW682CSl3m4XLEsFCeH24 zlh&HRdzZ#6bNniM<;Sgh#?6j{fIk`W(?jclN|IAF4haR<7*({qJgMS`hl0dqZzE|9< zjEMyeY^@>2D79s;Qs#yA)y>nZ!9S00US3|_Qc98)w$>zLq)Xz5u_UF07^56wutoVh8DS#B z(t~S|Q)|Wbdd1+M$G3DRY(%iH%-Xb18v1gD#`UL9bX}}h`z}}C&*s?Poelmue096s z8naHi5N4A6BZQ|^>$=LlG8)|XrrFcxb*29@wBPLDpTpN$Yk2SBy%)Eml)^mEvPgeS z$@^zgNB*2i^Y%%9Gleb5ecz=)!Fg2V;GfR_qZF1T(= { Advantage: VornachteileDataModel, Equipment: EquipmentDataModel, Liturgy: LiturgyDataModel, - Blessing: BlessingDataModel + Blessing: BlessingDataModel, + SpecialAbility: SpecialAbilityDataModel, + ActiveEffect: ActiveEffectDataModel, } CONFIG.Combat.initiative = { @@ -100,15 +107,26 @@ Hooks.once("init", () => { }) Items.registerSheet('dsa41.equipment', AusruestungSheet, { types: ["Equipment"], - makeDefault: true, + makeDefault: false, label: 'DSA41.AusruestungLabels.Item' }) Items.registerSheet('dsa41.liturgy', LiturgySheet, { + types: ["SpecialAbility"], + makeDefault: true, + label: 'DSA41.SpecialAbilityLabels.Item' + }) + Items.registerSheet('dsa41.specialAbility', SpecialAbilitySheet, { types: ["Liturgy"], makeDefault: true, label: 'DSA41.LiturgyLabels.Item' }) + Items.registerSheet('dsa41.activeEffect', ActiveEffectSheet, { + types: ['ActiveEffect'], + makeDefault: true, + label: 'DSA41.ActiveEffectLabels.ActiveFfect' + }) + return preloadHandlebarsTemplates(); }) diff --git a/src/module/data/activeeffect.mjs b/src/module/data/activeeffect.mjs new file mode 100644 index 00000000..929cb489 --- /dev/null +++ b/src/module/data/activeeffect.mjs @@ -0,0 +1,49 @@ +import BaseItem from "./base-item.mjs"; + +const {ArrayField, NumberField, StringField, HTMLField} = foundry.data.fields; + +export class ActiveEffectDataModel extends BaseItem { + + static defineSchema() { + return { + name: new StringField({required: true}), + notes: new HTMLField(), + } + /* + + name: String, // Name of Vornachteil will be used for rendering and referencing by other Items + description: HTMLString, // only used for rendering + variant: [String]?, // variant name of Vornachteil e.g. "Mut" in the case of "Herausragende Eigenschaft" + levels: [Number]?, // available levels e.g. 1, 2 in the case of "Flink" + mods: [ + { + level: Number?, // in reference to level of the Vornachteil, is null when it does not have any levels or is the only modification + field: String, // Reference to Actor Data e.g. "FF" maps to "FF.mod" + value: Number, // value of the Modification e.g. "+2" maps to 2 + requirement: { + field: String // Reference to Actor Data e.g. "BE" maps "be.aktuell" + operation: String // Supported: "<=", ">" + value: Number // Target Value the referenced field has to compare against + }? // optional when the mod does not have an active requirement + } + ] + + */ + } + + _onCreate(data, options, userId) { + super._onCreate(data, options, userId); + if (this.parent.getEmbeddedCollection("ActiveEffect").contents.length === 0) { + + + this.parent.createEmbeddedDocuments("ActiveEffect", [{ + name: data.name, + changes: [], + duration: {}, + icon: this.img, + }]); + console.log("added default activeffect"); + } + } + +} diff --git a/src/module/data/character.mjs b/src/module/data/character.mjs index eb5df953..10a47081 100644 --- a/src/module/data/character.mjs +++ b/src/module/data/character.mjs @@ -20,16 +20,17 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { professions: new ArrayField(new StringField()), geschlecht: new StringField(), haarfarbe: new StringField(), - groesse: new NumberField({required: true, integer: false}), + groesse: new StringField(), augenfarbe: new StringField(), geburtstag: new StringField(), - alter: new NumberField({required: true, integer: true}), - gewicht: new NumberField({required: true, integer: true}), + alter: new StringField(), + gewicht: new StringField(), aussehen: new HTMLField(), familie: new HTMLField(), titel: new StringField(), stand: new StringField(), }), + setEquipped: new NumberField({required: true, initial: 0, max: 3, integer: true}), ini: new SchemaField({ aktuell: new NumberField({required: true, integer: true, initial: 0}), mod: new NumberField({required: true, integer: true, initial: 0}), diff --git a/src/module/data/specialAbility.mjs b/src/module/data/specialAbility.mjs new file mode 100644 index 00000000..cd143ca6 --- /dev/null +++ b/src/module/data/specialAbility.mjs @@ -0,0 +1,12 @@ +import BaseItem from "./base-item.mjs"; + +const {BooleanField, NumberField, SchemaField, ArrayField, StringField, HTMLField} = foundry.data.fields; + +export class SpecialAbilityDataModel extends BaseItem { + + static defineSchema() { + return { + name: new StringField() + } + } +} diff --git a/src/module/documents/character.mjs b/src/module/documents/character.mjs index 08d1c6bc..4393b264 100644 --- a/src/module/documents/character.mjs +++ b/src/module/documents/character.mjs @@ -50,14 +50,50 @@ export class Character extends Actor { systemData.ini.aktuell = Math.round((mu + mu + _in + ge) / 5) + systemData.ini.mod; systemData.mr.aktuell = Math.round((mu + kl + ko) / 5) + systemData.mr.mod; - // evaluate deities for KaP systemData.rs = 0; + systemData.be = 0; + + // map current set to RS and BE + + const ausruestung = systemData.heldenausruestung[systemData.setEquipped]; + if (ausruestung) { + if (ausruestung.brust) { + systemData.rs += systemData.parent.items.get(ausruestung.brust).system.armorValue ?? 0 + systemData.be += systemData.parent.items.get(ausruestung.brust).system.armorHandicap ?? 0 + } + if (ausruestung.bauch) { + systemData.rs += systemData.parent.items.get(ausruestung.bauch).system.armorValue ?? 0 + systemData.be += systemData.parent.items.get(ausruestung.bauch).system.armorHandicap ?? 0 + } + if (ausruestung.ruecken) { + systemData.rs += systemData.parent.items.get(ausruestung.ruecken).system.armorValue ?? 0 + systemData.be += systemData.parent.items.get(ausruestung.ruecken).system.armorHandicap ?? 0 + } + if (ausruestung.armlinks) { + systemData.rs += systemData.parent.items.get(ausruestung.armlinks).system.armorValue ?? 0 + systemData.be += systemData.parent.items.get(ausruestung.armlinks).system.armorHandicap ?? 0 + } + if (ausruestung.armrechts) { + systemData.rs += systemData.parent.items.get(ausruestung.armrechts).system.armorValue ?? 0 + systemData.be += systemData.parent.items.get(ausruestung.armrechts).system.armorHandicap ?? 0 + } + if (ausruestung.beinlinks) { + systemData.rs += systemData.parent.items.get(ausruestung.beinlinks).system.armorValue ?? 0 + systemData.be += systemData.parent.items.get(ausruestung.beinlinks).system.armorHandicap ?? 0 + } + if (ausruestung.beinrechts) { + systemData.rs += systemData.parent.items.get(ausruestung.beinrechts).system.armorValue ?? 0 + systemData.be += systemData.parent.items.get(ausruestung.beinrechts).system.armorHandicap ?? 0 + } + } systemData.kap.max = 0; - const deities = systemData.parent.items.filter(p => p.type === "Blessing") + // evaluate deities for KaP + + const deities = systemData.parent.items.filter(p => p.type === "Blessing") deities?.forEach((deity) => { if (LiturgyData.alverans.includes(deity.system.gottheit)) { systemData.kap.max = 24; diff --git a/src/module/documents/specialAbility.mjs b/src/module/documents/specialAbility.mjs new file mode 100644 index 00000000..f3d30692 --- /dev/null +++ b/src/module/documents/specialAbility.mjs @@ -0,0 +1,9 @@ +export class SpecialAbility extends Item { + /** + * Augment the basic Item data model with additional dynamic data. + */ + prepareData() { + super.prepareData(); + } + +} diff --git a/src/module/sheets/ActiveEffectSheet.mjs b/src/module/sheets/ActiveEffectSheet.mjs new file mode 100644 index 00000000..99211ed2 --- /dev/null +++ b/src/module/sheets/ActiveEffectSheet.mjs @@ -0,0 +1,44 @@ +export class ActiveEffectSheet extends ItemSheet { + /**@override */ + static get defaultOptions() { + return foundry.utils.mergeObject(super.defaultOptions, { + classes: ['dsa41', 'sheet', 'activeeffect'], + width: 520, + height: 480 + }); + } + + /** @override */ + get template() { + return `systems/DSA_4-1/templates/item/item-activeeffect-sheet.hbs`; + } + + /** @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(); + const effects = context.document.getEmbeddedCollection("ActiveEffect").contents; + if (effects.length > 0) { + context.effectId = effects[0]._id; + } + + return context; + } + + activateListeners(html) { + super.activateListeners(html); + + // Everything below here is only needed if the sheet is editable + if (!this.isEditable) return; + + html.on('click', '.editEffects', (evt) => { + const {id} = evt.currentTarget.dataset; + const effect = this.object.effects.get(id); + effect.sheet.render(true); + }) + } + +} diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index b0d6aa32..f144a16f 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -39,10 +39,14 @@ export class CharacterSheet extends ActorSheet { 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; } @@ -117,10 +121,14 @@ export class CharacterSheet extends ActorSheet { 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 ?? []; this.#addSkillsToContext(context) this.#addAdvantagesToContext(context) - this.#addAttributesToContext(context) + this.#addSpecialAbilitiesToContext(context) + await this.#addAttributesToContext(context) this.#addEquipmentsToContext(context) await this.#addCombatStatistics(context) this.#addActionsToContext(context) @@ -158,56 +166,79 @@ export class CharacterSheet extends ActorSheet { context.hasSpells = context.spells.length > 0; } - #addAttributesToContext(context) { - const actorData = context.data; + 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') + } context.attributes = [ { eigenschaft: "mu", name: "MU", tooltip: "Mut", - wert: actorData.system.attribute.mu.aktuell ?? 0, + wert: (context.derived.attribute.mu.aktuell + context.derived.attribute.mu.mod) ?? 0, }, { eigenschaft: "kl", name: "KL", tooltip: "Klugheit", - wert: actorData.system.attribute.kl.aktuell ?? 0, + wert: (context.derived.attribute.kl.aktuell + context.derived.attribute.kl.mod) ?? 0, }, { eigenschaft: "in", name: "IN", tooltip: "Intuition", - wert: actorData.system.attribute.in.aktuell ?? 0, + wert: (context.derived.attribute.in.aktuell + context.derived.attribute.in.mod) ?? 0, }, { eigenschaft: "ch", name: "CH", tooltip: "Charisma", - wert: actorData.system.attribute.ch.aktuell ?? 0, + wert: (context.derived.attribute.ch.aktuell + context.derived.attribute.ch.mod) ?? 0, }, { eigenschaft: "ff", name: "FF", tooltip: "Fingerfertigkeit", - wert: actorData.system.attribute.ff.aktuell ?? 0, + wert: (context.derived.attribute.ff.aktuell + context.derived.attribute.ff.mod) ?? 0, }, { eigenschaft: "ge", name: "GE", tooltip: "Geschicklichkeit", - wert: actorData.system.attribute.ge.aktuell ?? 0, + wert: (context.derived.attribute.ge.aktuell + context.derived.attribute.ge.mod) ?? 0, }, { eigenschaft: "ko", name: "KO", tooltip: "Konstitution", - wert: actorData.system.attribute.ko.aktuell ?? 0, + wert: (context.derived.attribute.ko.aktuell + context.derived.attribute.ko.mod) ?? 0, }, { eigenschaft: "kk", name: "KK", tooltip: "Körperkraft", - wert: actorData.system.attribute.kk.aktuell ?? 0, + wert: (context.derived.attribute.kk.aktuell + context.derived.attribute.kk.mod) ?? 0, }, ]; @@ -231,12 +262,22 @@ export class CharacterSheet extends ActorSheet { ); } - #findEquipmentOnSlot(slot, setNumber) { - return this.object.items.get(this.object.system.heldenausruestung[setNumber][slot]) + #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, + }); + } + } + ); } - #findTalentsOfEquipment(equipment) { - + #findEquipmentOnSlot(slot, setNumber) { + return this.object.items.get(this.object.system.heldenausruestung[setNumber]?.[slot]) } #addActionsToContext(context) { @@ -244,14 +285,16 @@ export class CharacterSheet extends ActorSheet { context.actions = am.evaluate() } - #isWorn(itemId, setId) { + #isWorn(itemId) { const slots = PlayerCharacterDataModel.getSlots() - const set = this.object.system.heldenausruestung[setId] - for (const slot of slots) { - const equipmentSlotId = set[slot] - if (equipmentSlotId === itemId) { - return slot + 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 + } } } @@ -273,9 +316,9 @@ export class CharacterSheet extends ActorSheet { context.aupcurrent = context.actor.system.aup.aktuell ?? 0 - const fernkampf = this.#findEquipmentOnSlot("fernkampf", 0) - const links = this.#findEquipmentOnSlot("links", 0) - const rechts = this.#findEquipmentOnSlot("rechts", 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) { @@ -344,16 +387,24 @@ export class CharacterSheet extends ActorSheet { 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 ?? 0, - worn: this.#isWorn(item._id, 0) + weight: item.system.weight, + worn: this.#isWorn(item._id) }) - context.carryingweight += item.system.quantity * item.system.weight; + context.carryingweight += item.system.quantity * effectiveWeight; } }) context.maxcarryingcapacity = actorData.system.attribute.kk.aktuell @@ -698,6 +749,20 @@ export class CharacterSheet extends ActorSheet { } } + 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 + actor.deleteEmbeddedDocuments('Item', [array[i].id]).then(() => { + console.log("await") + }) + + return true; + } + } + } + #handleDroppedAdvantage(actor, advantage) { const array = Array.from(actor.items); for (let i = 0; i < array.length; i++) { @@ -713,7 +778,7 @@ export class CharacterSheet extends ActorSheet { const tabs = new Tabs({ navSelector: ".paperdoll-tabs.tabs", contentSelector: ".sheet-body.paperdoll-sets", - initial: "set1" + initial: "set" + (this.object.system.setEquipped + 1) }); tabs.bind(html[0]); @@ -721,6 +786,12 @@ export class CharacterSheet extends ActorSheet { 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', '.talent.rollable', (evt) => { this._onTalentRoll(evt); }); @@ -912,4 +983,13 @@ export class CharacterSheet extends ActorSheet { } } + #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; + } + } + } + } diff --git a/src/module/sheets/specialAbilitySheet.mjs b/src/module/sheets/specialAbilitySheet.mjs new file mode 100644 index 00000000..7f979941 --- /dev/null +++ b/src/module/sheets/specialAbilitySheet.mjs @@ -0,0 +1,49 @@ +export class SpecialAbilitySheet extends ItemSheet { + /**@override */ + static get defaultOptions() { + return foundry.utils.mergeObject(super.defaultOptions, { + classes: ['dsa41', 'sheet', 'item', 'specialability'], + width: 520, + height: 480, + tabs: [ + { + navSelector: '.sheet-tabs', + contentSelector: '.sheet-body', + initial: 'description', + }, + ], + }); + } + + /** @override */ + get template() { + return `systems/DSA_4-1/templates/item/item-special-ability-sheet.hbs`; + } + + /** @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. + const advantageData = context.data; + + // Add the actor's data to context.data for easier access, as well as flags. + context.system = advantageData.system; + context.flags = advantageData.flags; + context.json = JSON.stringify(advantageData.system, null, 4); + + return context; + } + + activateListeners(html) { + super.activateListeners(html); + + // Everything below here is only needed if the sheet is editable + if (!this.isEditable) + } + +} diff --git a/src/style/_active-effect-sheet.scss b/src/style/_active-effect-sheet.scss new file mode 100644 index 00000000..dd1dddb0 --- /dev/null +++ b/src/style/_active-effect-sheet.scss @@ -0,0 +1,38 @@ +.active-effect { + + display: flex; + flex-direction: column; + + .header { + flex: 0; + display: grid; + grid-template-columns: 48px 1fr 48px; + grid-template-rows: 48px; + gap: 8px; + + input { + height: 48px; + line-height: 48px; + } + } + + .meta { + flex: 1; + display: flex; + flex-direction: column; + margin-top: 8px; + + label { + flex: 0; + } + + div.editor { + flex: 1; + border: 1px inset #ccc; + background-color: rgba(0, 0, 0, 0.2) + } + + + } + +} diff --git a/src/style/_character-sheet.scss b/src/style/_character-sheet.scss index df3d6709..6a671515 100644 --- a/src/style/_character-sheet.scss +++ b/src/style/_character-sheet.scss @@ -79,6 +79,7 @@ display: grid; grid-template-columns: 1fr 1fr; grid-template-areas: 'label label' 'left right'; + gap: 0 8px; label { grid-area: label; @@ -114,6 +115,130 @@ } + .tab.attributes.active { + height: 100%; + + .attribute { + padding: 8px 0; + display: flex; + gap: 0 8px; + + label { + width: 120px; + text-align: right; + vertical-align: middle; + line-height: 24px; + } + + input { + max-width: 80px; + text-align: right; + } + + .mod { + color: grey; + text-shadow: 0 -1px 0 #ccc; + box-Shadow: 1px 1px 1px rgba(0, 0, 0, 0.5); + border-radius: 4px; + height: 24px; + width: 24px; + background: linear-gradient(0deg, rgba(24, 24, 24, 1) 0%, rgba(80, 80, 80, 1) 100%);; + display: inline-block; + text-align: center; + vertical-align: middle; + line-height: 24px; + margin-left: 4px; + } + + } + + .attributes-overview { + + columns: 2; + gap: 0 16px; + + } + + .resource-overview { + + .attribute { + + } + + } + + .advantages, .special-abilities { + margin-bottom: 16px; + + ul { + list-style-type: none; + padding: 0; + margin: 0; + text-indent: 0; + + li { + display: inline-block; + } + + .advantage, .special-ability { + position: relative; + border: 1px solid gold; + box-shadow: 2px 2px 4px #000; + border-radius: 8px; + height: 24px; + color: gold; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2); + display: inline-block; + padding: 0 8px; + margin-left: 0; + margin-bottom: 4px; + background-image: url("../assets/velvet_button.png"); + background-repeat: repeat-y; + background-size: cover; + + span { + position: relative; + z-index: 2; + line-height: 24px; + vertical-align: middle; + } + + &.special-ability { + &::after { + background: rgba(128, 0, 96, 0.5); + } + } + + &::after { + content: ""; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + border-radius: 8px; + background: rgba(0, 128, 0, 0.5); + } + + & + .advantage, & + .special-ability { + margin-left: 8px; + } + + &.nachteil { + font-style: italic; + + &::after { + background: rgba(128, 0, 0, 0.5); + } + } + } + } + + } + + + } + .backpack.active { padding: 8px; display: grid; diff --git a/src/style/styles.scss b/src/style/styles.scss index e11377af..1f61b26b 100644 --- a/src/style/styles.scss +++ b/src/style/styles.scss @@ -11,3 +11,4 @@ @use "_player-action"; @use "_modify-liturgy"; @use "_liturgy-banner"; +@use "_active-effect-sheet"; diff --git a/src/system.json b/src/system.json index ffd4083f..847fe30a 100644 --- a/src/system.json +++ b/src/system.json @@ -163,6 +163,14 @@ "maxLEP", "maxMR" ] + }, + "SpecialAbility": { + "stringFields": [ + "name" + ] + }, + "ActiveEffect": { + }, "Skill": { "stringFields": [ diff --git a/src/templates/actor/actor-character-sheet.hbs b/src/templates/actor/actor-character-sheet.hbs index 2ca6af31..108caddf 100644 --- a/src/templates/actor/actor-character-sheet.hbs +++ b/src/templates/actor/actor-character-sheet.hbs @@ -13,8 +13,9 @@
-

- +

+
+
+
+ + +
+ {{#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}} +
+ +
+
+ + +
+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+

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}} +
+
@@ -160,6 +278,12 @@ {{derived.rs}}
+
+ + {{derived.be}} +
+ +
@@ -298,7 +422,11 @@ data-target="{{this.target}}" data-actor="{{../../actor.id}}">
{{/each}} - + {{#if (eq ../actor.system.setEquipped @index)}} + + {{else}} + + {{/if}} @@ -559,8 +687,10 @@ {{/if}} + {{#if this.hasPets}}
+ {{/if}} diff --git a/src/templates/item/item-activeeffect-sheet.hbs b/src/templates/item/item-activeeffect-sheet.hbs new file mode 100644 index 00000000..e7c02a70 --- /dev/null +++ b/src/templates/item/item-activeeffect-sheet.hbs @@ -0,0 +1,20 @@ +
+
+ +
+ + + + +
+ +
+ + {{editor item.system.notes target="system.notes" button=true owner=owner editable=editable}} +
+ + +
+
diff --git a/src/templates/ui/partial-equipment-button.hbs b/src/templates/ui/partial-equipment-button.hbs index 37e310b6..f6503019 100644 --- a/src/templates/ui/partial-equipment-button.hbs +++ b/src/templates/ui/partial-equipment-button.hbs @@ -15,7 +15,7 @@ {{this.name}} {{this.quantity}} - {{this.weight}} + {{#if this.worn}}({{/if}}{{this.weight}}{{#if this.worn}}){{/if}} {{/each}} diff --git a/src/templates/ui/partial-sf-button.hbs b/src/templates/ui/partial-sf-button.hbs new file mode 100644 index 00000000..40531690 --- /dev/null +++ b/src/templates/ui/partial-sf-button.hbs @@ -0,0 +1,3 @@ +
+ {{this.name}} +