diff --git a/src/module/sheets/character-standalone/advsf.mjs b/src/module/sheets/character-standalone/advsf.mjs new file mode 100644 index 00000000..11777bbf --- /dev/null +++ b/src/module/sheets/character-standalone/advsf.mjs @@ -0,0 +1,118 @@ +const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api +const {ActorSheetV2} = foundry.applications.sheets + +export class StandaloneADVSF extends HandlebarsApplicationMixin(ActorSheetV2) { + + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + position: {width: 520, height: 480}, + classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'advsf'], + tag: 'form', + actions: { + rollFlaw: StandaloneADVSF.#rollFlaw, + openEmbeddedDocument: StandaloneADVSF.#openEmbeddedDocument, + + } + } + + /** @inheritDoc */ + static PARTS = { + form: { + template: `systems/DSA_4-1/templates/actor/character/standalone/advsf.hbs` + } + } + + _actor = null + + constructor(actor) { + super(actor) + this._actor = actor + this.render(true) + this.options.window.title = `${this.document.name} Vor und Nachteile` + } + + static async #rollFlaw(event, target) { + this._actor?.sheet.options.actions.rollFlaw.bind(this)(event, target) + } + + static async #openEmbeddedDocument(event, target) { + this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target) + } + + _configureRenderOptions(options) { + super._configureRenderOptions(options) + + options.window.title = `${this.document.name}: Vor und Nachteile` + + return options + } + + async _prepareContext(context, options, object) { + if (this._actor) { + const actorData = this.document + context.system = actorData.system + context.flags = actorData.flags + context.derived = actorData.system + context.originalName = actorData.name + context.name = context.derived.name ?? actorData.name + context.effects = actorData.effects ?? [] + context.advantages = [] + context.flaws = [] + + actorData.itemTypes.Advantage.forEach((item) => { + if (!item.system.schlechteEigenschaft) { + 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, + fav: item.getFlag("DSA_4-1", "favourite") + }) + } else { + context.flaws.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, + fav: item.getFlag("DSA_4-1", "favourite") + }) + } + } + ) + + context.specialAbilities = [] + actorData.itemTypes.SpecialAbility.forEach((item) => { + context.specialAbilities.push({ + id: item._id, + name: item.system.value ? item.system.value : item.name, + fav: item.getFlag("DSA_4-1", "favourite") + }); + } + ); + + return context + } + } + + _onRender(context, options) { + if (this._actor) { + new foundry.applications.ux.DragDrop.implementation({ + dropSelector: ".advantages, .special-abilities", + permissions: { + drop: this._actor.sheet._canDragDrop.bind(this._actor.sheet) + }, + callbacks: { + drop: this._actor.sheet._onDrop.bind(this._actor.sheet), + } + }).bind(this.element); + } + } +} \ No newline at end of file diff --git a/src/module/sheets/character-standalone/bagpack.mjs b/src/module/sheets/character-standalone/bagpack.mjs new file mode 100644 index 00000000..24a52224 --- /dev/null +++ b/src/module/sheets/character-standalone/bagpack.mjs @@ -0,0 +1,98 @@ +const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api +const {ActorSheetV2} = foundry.applications.sheets + +export class Bagpack extends HandlebarsApplicationMixin(ActorSheetV2) { + + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + position: {width: 520, height: 480}, + classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'bagpack'], + tag: 'form', + actions: { + openItemBrowser: Bagpack.#openItemBrowser, + newItem: Bagpack.#newItem, + openEmbeddedDocument: Bagpack.#openEmbeddedDocument, + + } + } + + /** @inheritDoc */ + static PARTS = { + form: { + template: `systems/DSA_4-1/templates/actor/character/standalone/bagpack.hbs` + } + } + + _actor = null + + constructor(actor) { + super(actor) + this._actor = actor + this.render(true) + } + + static async #openItemBrowser(event, target) { + this._actor?.sheet.options.actions.openItemBrowser().bind(this)(event, target) + } + + static async #newItem(event, target) { + this._actor?.sheet.options.actions.newItem.bind(this)(event, target) + } + + static async #openEmbeddedDocument(event, target) { + this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target) + } + + _configureRenderOptions(options) { + super._configureRenderOptions(options) + + options.window.title = `${this.document.name}: Inventar` + + return options + } + + async _prepareContext(context, options, object) { + const actorData = this.document + context.system = actorData.system + context.flags = actorData.flags + + context.equipments = [] + context.carryingweight = 0 + actorData.itemTypes["Equipment"].sort((a, b) => a.sort - b.sort).forEach((item, index) => { + + // worn items are halved weight + + let effectiveWeight = item.system.weight ?? 0 + if (this.document.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.document.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); + + context.wealth = 0 + + actorData.itemTypes["Equipment"].forEach(coin => { + if (coin.system.category.indexOf("Währung") !== -1) { + context.wealth += (coin.system.quantity * coin.system.currencyDenominator) + } + }) + + return context + } + + _onRender(context, options) { + } +} \ No newline at end of file diff --git a/src/module/sheets/character-standalone/skills.mjs b/src/module/sheets/character-standalone/skills.mjs new file mode 100644 index 00000000..7d752bb6 --- /dev/null +++ b/src/module/sheets/character-standalone/skills.mjs @@ -0,0 +1,127 @@ +const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api +const {ActorSheetV2} = foundry.applications.sheets + +export class StandaloneSkills extends HandlebarsApplicationMixin(ActorSheetV2) { + + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + position: {width: 520, height: 480}, + classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'skills'], + tag: 'form', + actions: { + rollCombatSkill: StandaloneSkills.#rollCombatSkill, + rollSkill: StandaloneSkills.#rollSkill, + openEmbeddedDocument: StandaloneSkills.#openEmbeddedDocument, + + } + } + + /** @inheritDoc */ + static PARTS = { + form: { + template: `systems/DSA_4-1/templates/actor/character/standalone/skills.hbs` + } + } + + _actor = null + + constructor(actor) { + super(actor) + this._actor = actor + this.render(true) + } + + static async #rollCombatSkill(event, target) { + this._actor?.sheet.options.actions.rollCombatSkill.bind(this)(event, target) + } + + static async #rollSkill(event, target) { + this._actor?.sheet.options.actions.rollSkill.bind(this)(event, target) + } + + static async #openEmbeddedDocument(event, target) { + this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target) + } + + _configureRenderOptions(options) { + super._configureRenderOptions(options) + + options.window.title = `${this.document.name}: Talente` + + return options + } + + async _prepareContext(context, options, object) { + const actorData = this.document + context.system = actorData.system + context.flags = actorData.flags + context.derived = this.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 = []; + + actorData.itemTypes.Skill.forEach((item, index) => { + + 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.replace(/Sprachen kennen/g, "Sprache:").replace(/Lesen\/Schreiben/g, "Schrift: "), + 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, + fav: item.getFlag("DSA_4-1", "favourite") + }; + + 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); + } + ) + + return context + } + + _onRender(context, options) { + } +} \ No newline at end of file diff --git a/src/module/sheets/character/skills.mjs b/src/module/sheets/character/skills.mjs index 8c868d44..319f1f58 100644 --- a/src/module/sheets/character/skills.mjs +++ b/src/module/sheets/character/skills.mjs @@ -2,7 +2,6 @@ export default { _prepareContext: (context) => { const actorData = context.document - context.spells = [] context.system = actorData.system context.flags = actorData.flags context.derived = context.document.system diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index 4876b906..91457d1a 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -16,6 +16,9 @@ import {TalentDialog} from "../dialog/talentDialog.mjs"; import {AttributeDialog} from "../dialog/attributeDialog.mjs"; import {ItemBrowserDialog} from "../dialog/itemBrowserDialog.mjs"; import * as EquipmentDocument from "../documents/equipment.mjs"; +import {StandaloneADVSF} from "./character-standalone/advsf.mjs"; +import {StandaloneSkills} from "./character-standalone/skills.mjs"; +import {Bagpack} from "./character-standalone/bagpack.mjs"; const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api const {ActorSheetV2} = foundry.applications.sheets @@ -39,24 +42,27 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { actions: { rollCombatSkill: CharacterSheet.#rollCombatSkill, rollSkill: CharacterSheet.#rollSkill, - rollFlaw: CharacterSheet.#rollFlaw, + rollFlaw: CharacterSheet.rollFlaw, rollAttribute: CharacterSheet.#rollAttribute, editImage: DocumentSheetV2.DEFAULT_OPTIONS.actions.editImage, - openEmbeddedDocument: CharacterSheet.#openEmbeddedDocument, + openEmbeddedDocument: CharacterSheet.openEmbeddedDocument, openCultureDocument: CharacterSheet.#openCultureDocument, openSpeciesDocument: CharacterSheet.#openSpeciesDocument, openCombatAction: CharacterSheet.#openCombatAction, - openLiturgyDialog: CharacterSheet.#openLiturgyDialog, - openSpellDialog: CharacterSheet.#openSpellDialog, + openLiturgyDialog: CharacterSheet.openLiturgyDialog, + openSpellDialog: CharacterSheet.openSpellDialog, progressCooldown: CharacterSheet.#progressCooldown, cancelCooldown: CharacterSheet.#cancelCooldown, activateCooldown: CharacterSheet.#activateCooldown, rest: CharacterSheet.#startResting, removeEffect: CharacterSheet.#removeEffect, rollDamage: CharacterSheet.#rollDamage, - openItemBrowser: CharacterSheet.#openItemBrowser, - newItem: CharacterSheet.#addNewItem, - toggleFav: CharacterSheet.#toggleFav, + openItemBrowser: CharacterSheet.openItemBrowser, + newItem: CharacterSheet.addNewItem, + toggleFav: CharacterSheet.toggleFav, + openStandaloneADVSF: CharacterSheet.#openStandaloneADVSF, + openStandaloneSkills: CharacterSheet.#openStandaloneSkills, + openBagpack: CharacterSheet.#openBagpack } } @@ -144,7 +150,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { }).render(true) } - static async #rollFlaw(event, target) { + static async rollFlaw(event, target) { new AttributeDialog(this.document, target.dataset.itemId).render(true) } @@ -199,7 +205,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { * * @param {MouseEvent} event */ - static #openEmbeddedDocument(event) { + static openEmbeddedDocument(event) { let dataset = event.target.dataset if (!dataset.itemId && !dataset.id) { dataset = event.target.parentElement.dataset @@ -230,12 +236,12 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { } } - static #openLiturgyDialog(event, target) { + static openLiturgyDialog(event, target) { const {id, lkp, deity} = target.dataset new LiturgyDialog(this.document, lkp, id, deity).render(true) } - static #openSpellDialog(event, target) { + static openSpellDialog(event, target) { const {itemId} = target.dataset console.log(itemId) this.document.itemTypes["Spell"]?.find(p => p.id === itemId)?.sheet.render(true) @@ -262,11 +268,11 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { } - static async #openItemBrowser(event, target) { + static async openItemBrowser(event, target) { new ItemBrowserDialog(this.document).render(true) } - static async #addNewItem(event, target) { + static async addNewItem(event, target) { let item = new EquipmentDocument.Equipment({ name: "Neuer Gegenstand", type: "Equipment", @@ -275,7 +281,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { items[0].sheet.render(true) } - static async #toggleFav(event, target) { + static async toggleFav(event, target) { const {itemId} = target.dataset const doc = this.document.items.find(p => p.id === itemId) @@ -285,6 +291,30 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { } } + static async #openStandaloneADVSF(event, target) { + new StandaloneADVSF(this.document) + } + + static async #openStandaloneHealth(event, target) { + new StandaloneHealth(this.document) + } + + static async #openStandaloneSkills(event, target) { + new StandaloneSkills(this.document) + } + + static async #openBagpack(event, target) { + new Bagpack(this.document) + } + + static async #openStandaloneSpells(event, target) { + new StandaloneSpells(this.document) + } + + static async #openStandaloneLiturgies(event, target) { + new StandaloneLiturgies(this.document) + } + _configureRenderOptions(options) { super._configureRenderOptions(options) @@ -655,9 +685,12 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { if (position.width < 300) { this.element.classList.add("tiny") + this.element.querySelector(".sidebuttons").style.left = (position.width + position.left) + "px" + this.element.querySelector(".sidebuttons").style.top = (position.top) + "px" } else { this.element.classList.remove("tiny") } + } _onRender(context, options) { diff --git a/src/style/atoms/_typography.scss b/src/style/atoms/_typography.scss index a56c325e..ca5c1f46 100644 --- a/src/style/atoms/_typography.scss +++ b/src/style/atoms/_typography.scss @@ -25,6 +25,7 @@ input, .cooldown > span, + .mini-skill, .mini-weaponskill, .mini-language-skill, .attribute.rollable > .name, .attribute.rollable > .wert { font-family: Andalus, sans-serif; diff --git a/src/style/molecules/_sidebar-elements.scss b/src/style/molecules/_sidebar-elements.scss index 62354506..e87381e8 100644 --- a/src/style/molecules/_sidebar-elements.scss +++ b/src/style/molecules/_sidebar-elements.scss @@ -157,6 +157,33 @@ } } + .favourites { + + h3 { + text-align: center; + margin: 8px 0; + } + + .mini-skill, .mini-weaponskill, .mini-language-skill { + background-image: url("/systems/DSA_4-1/assets/velvet_button.png"); + background-repeat: repeat-y; + background-size: cover; + + border: 1px outset #ccc; + + color: white; + border-radius: 4px; + padding: 0 8px; + margin-bottom: 4px; + cursor: pointer; + + &:hover { + text-shadow: 0 0 2px rgba(255, 0, 0, 1); + } + } + + } + .cooldowns { h3 { diff --git a/src/style/organisms/_character-sheet.scss b/src/style/organisms/_character-sheet.scss index 163ef47b..887f0e4e 100644 --- a/src/style/organisms/_character-sheet.scss +++ b/src/style/organisms/_character-sheet.scss @@ -111,9 +111,12 @@ @include liturgies.tab; } + .sidebuttons { + display: none; + } } - &.tiny { + &.tiny:not(.minimized):not(.minimizing) { .header-fields { & > div:not(.attributes) { @@ -151,6 +154,29 @@ section.tab.tab.tab { display: none; } + + .sidebuttons { + position: fixed; + display: block; + margin-left: -136px; + margin-top: 182px; + pointer-events: none; + rotate: 90deg; + + div { + display: flex; + gap: 4px; + + button { + background-image: url("/systems/DSA_4-1/assets/velvet_button.png"); + background-repeat: repeat-y; + background-size: cover; + color: white; + font-weight: bold; + pointer-events: all; + } + } + } } } diff --git a/src/style/organisms/character-tabs/_advsf.scss b/src/style/organisms/character-tabs/_advsf.scss index 7d7834c9..8fc7af3d 100644 --- a/src/style/organisms/character-tabs/_advsf.scss +++ b/src/style/organisms/character-tabs/_advsf.scss @@ -98,3 +98,11 @@ } } + +.dsa41.actor.character.standalone.advsf { + @include tab; + + .advantages-and-specialabilities { + flex-direction: column; + } +} diff --git a/src/style/organisms/character-tabs/_inventory.scss b/src/style/organisms/character-tabs/_inventory.scss index ecb35fb7..d8c96658 100644 --- a/src/style/organisms/character-tabs/_inventory.scss +++ b/src/style/organisms/character-tabs/_inventory.scss @@ -114,3 +114,52 @@ } } } + +.dsa41.sheet.actor.character.standalone.bagpack { + @include tab; + + + .coinage { + position: absolute; + bottom: 0; + right: 8px; + height: 38px; + line-height: 38px; + vertical-align: middle; + } + + .capacity { + position: absolute; + top: 0; + left: 0; + right: 0; + } + + .buttons { + position: absolute; + bottom: 4px; + left: 4px; + + button { + display: inline-block; + } + + } + + .inventory-table { + overflow-x: hidden; + overflow-y: auto; + + position: absolute; + left: 4px; + top: 4px; + right: 4px; + bottom: 38px; + + .equipment { + @include equipment.equipment + } + + } +} + diff --git a/src/style/organisms/character-tabs/_skills.scss b/src/style/organisms/character-tabs/_skills.scss index bbb542d0..e9acdc57 100644 --- a/src/style/organisms/character-tabs/_skills.scss +++ b/src/style/organisms/character-tabs/_skills.scss @@ -45,4 +45,18 @@ } } +} + +.mini-skills { + overflow-x: hidden; + overflow-y: auto; + height: 100%; + @include tab; + + container: unset; + + ul { + list-style-type: none; + padding-left: 0; + } } \ No newline at end of file diff --git a/src/templates/actor/character/main-sheet.hbs b/src/templates/actor/character/main-sheet.hbs index 386fc6b9..8f88ea7c 100644 --- a/src/templates/actor/character/main-sheet.hbs +++ b/src/templates/actor/character/main-sheet.hbs @@ -128,4 +128,17 @@ {{/each}} +
+
+ + + + + {{#if this.hasLiturgies}} + {{/if}} + {{#if this.hasSpells}} + {{/if}} +
+
+ diff --git a/src/templates/actor/character/standalone/advsf.hbs b/src/templates/actor/character/standalone/advsf.hbs new file mode 100644 index 00000000..13434596 --- /dev/null +++ b/src/templates/actor/character/standalone/advsf.hbs @@ -0,0 +1,26 @@ +
+
+

Schlechte Eigenschaften

+ +
+
+

Vor- und Nachteile

+ +
+
+

Sonderfertigkeiten

+ +
+
diff --git a/src/templates/actor/character/standalone/bagpack.hbs b/src/templates/actor/character/standalone/bagpack.hbs new file mode 100644 index 00000000..1ab325de --- /dev/null +++ b/src/templates/actor/character/standalone/bagpack.hbs @@ -0,0 +1,20 @@ +
+
+ +
+ +
+ +
+ + +
+ + +
+ + + {{> "systems/DSA_4-1/templates/ui/partial-equipment-button.hbs" equipments}} + +
diff --git a/src/templates/actor/character/standalone/skills.hbs b/src/templates/actor/character/standalone/skills.hbs new file mode 100644 index 00000000..67ff834e --- /dev/null +++ b/src/templates/actor/character/standalone/skills.hbs @@ -0,0 +1,97 @@ +
+
+
+

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