From 3ba588a3c17dbeb97d28b02c507bf1f04a7b11d6 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Sun, 5 Jan 2025 23:28:29 -0700 Subject: [PATCH 001/246] RC-31 | Armour | Table Setup --- langs/en-ca.json | 10 +++- templates/Apps/HeroSummaryCardV1/content.hbs | 44 ++++++++++++++++- templates/Apps/HeroSummaryCardV1/style.css | 50 ++++++++++++++++++++ 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/langs/en-ca.json b/langs/en-ca.json index 460e963..6f9b392 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -34,6 +34,7 @@ "singular": "Weapon", "plural": "Weapons" }, + "armour": "Armour", "wear": "Wear", "damage": "Damage", "guts": "Guts", @@ -46,7 +47,14 @@ "gold": "Gold", "silver": "Silver", "copper": "Copper" - } + }, + "anatomy": { + "head": "Head", + "body": "Body", + "arms": "Arms", + "legs": "Legs" + }, + "shield": "Shield" }, "setting": { "abbrAccess": { diff --git a/templates/Apps/HeroSummaryCardV1/content.hbs b/templates/Apps/HeroSummaryCardV1/content.hbs index 9fa9812..0c6c508 100644 --- a/templates/Apps/HeroSummaryCardV1/content.hbs +++ b/templates/Apps/HeroSummaryCardV1/content.hbs @@ -18,7 +18,49 @@ > {{!-- * Armour --}} -
+
+
+ {{ rc-i18n "RipCrypt.common.armour" }} +
+
+
+
0
+ {{ rc-i18n "RipCrypt.common.anatomy.head" }} +
+
+
0
+ {{ rc-i18n "RipCrypt.common.anatomy.body" }} +
+
+
0
+ {{ rc-i18n "RipCrypt.common.anatomy.arms" }} +
+
+
0
+ {{ rc-i18n "RipCrypt.common.anatomy.legs" }} +
+
+ {{ rc-i18n "RipCrypt.common.shield" }} +
+
+ +
{{!-- * Fate & Advancement --}}
diff --git a/templates/Apps/HeroSummaryCardV1/style.css b/templates/Apps/HeroSummaryCardV1/style.css index 8d23752..d508632 100644 --- a/templates/Apps/HeroSummaryCardV1/style.css +++ b/templates/Apps/HeroSummaryCardV1/style.css @@ -153,6 +153,11 @@ z-index: 2; } + &.small { + --size: 30px; + font-size: 1.15rem; + } + &.dual { font-size: var(--font-size-14); --distance-from-edge: 4px; @@ -185,4 +190,49 @@ } } } + + .armour { + grid-column: -2 / span 1; + grid-row: 1 / -1; + display: grid; + grid-template-rows: subgrid; + + .section-header { + text-align: right; + } + + .person { + grid-row: 2 / span 9; + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + grid-template-rows: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.2fr); + justify-items: center; + align-items: center; + + > div { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + } + + /* Positioning */ + .head, .body, .legs { grid-column: 1; } + .arms, .shield { grid-column: 2; } + .head { grid-row: 1; } + .body, .arms { grid-row: 2; } + .legs, .shield { grid-row: 3; } + .shield { align-self: end; } + + .armour-items { + display: contents; + + > li { + display: flex; + flex-direction: row-reverse; + justify-content: space-between; + } + } + } } From 08aab4c6ab2016991b17dcea4cb1bd257aaa5bfb Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Mon, 6 Jan 2025 18:12:01 -0700 Subject: [PATCH 002/246] RC-78 | Weapons | Fix Table Row Alignments --- templates/Apps/HeroSummaryCardV1/style.css | 7 +++++-- templates/css/elements/lists.css | 7 ++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/templates/Apps/HeroSummaryCardV1/style.css b/templates/Apps/HeroSummaryCardV1/style.css index d508632..1f8ef4f 100644 --- a/templates/Apps/HeroSummaryCardV1/style.css +++ b/templates/Apps/HeroSummaryCardV1/style.css @@ -90,7 +90,7 @@ grid-row: 7 / span 5; display: grid; grid-template-columns: subgrid; - grid-auto-rows: min-content; + grid-template-rows: subgrid; overflow-y: auto; thead, @@ -121,7 +121,10 @@ label, .label { width: 100%; - text-align: center; + height: 100%; + display: flex; + justify-content: center; + align-items: center; } } diff --git a/templates/css/elements/lists.css b/templates/css/elements/lists.css index 0f7b75d..6acaf06 100644 --- a/templates/css/elements/lists.css +++ b/templates/css/elements/lists.css @@ -7,7 +7,6 @@ > li { margin: 0; - padding: 2px 4px; display: flex; flex-direction: row; gap: 8px; @@ -31,4 +30,10 @@ right: 4px; } } + + ul { + > li { + margin: 0; + } + } } From 21ca3e067bddec2ad278160591fa27d178e3c834 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Mon, 6 Jan 2025 18:12:10 -0700 Subject: [PATCH 003/246] Update system manifest --- system.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system.json b/system.json index c717ddc..d6f4e28 100644 --- a/system.json +++ b/system.json @@ -4,8 +4,8 @@ "description": "", "version": "0.0.1", "compatibility": { - "minimum": 12, - "verified": 12, + "minimum": 13, + "verified": 13, "maximum": 13 }, "authors": [ @@ -36,7 +36,7 @@ "flags": { "hotReload": { "extensions": ["css", "hbs", "json", "mjs", "svg"], - "paths": ["assets", "Apps", "langs", "module"] + "paths": ["assets", "templates", "langs", "module"] } }, "documentTypes": { From 94c89f72e10d169cbbd244cd13c4c10b9040395f Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Wed, 8 Jan 2025 21:16:04 -0700 Subject: [PATCH 004/246] RC-80 | Setup Item Sheet --- langs/en-ca.json | 1 + module/Apps/ItemSheets/AllItemSheetV1.mjs | 50 +++++++++++++++++++++++ module/hooks/init.mjs | 15 +++++++ templates/Apps/AllItemSheetV1/content.hbs | 3 ++ templates/Apps/AllItemSheetV1/style.css | 3 ++ templates/Apps/apps.css | 1 + 6 files changed, 73 insertions(+) create mode 100644 module/Apps/ItemSheets/AllItemSheetV1.mjs create mode 100644 templates/Apps/AllItemSheetV1/content.hbs create mode 100644 templates/Apps/AllItemSheetV1/style.css diff --git a/langs/en-ca.json b/langs/en-ca.json index 6f9b392..5103805 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -9,6 +9,7 @@ }, "RipCrypt": { "sheet-names": { + "AllItemsSheetV1": "RipCrypt Item Sheet", "HeroSummaryCardV1": "Hero Stat Card", "HeroSkillsCardV1": "Hero Skill Card" }, diff --git a/module/Apps/ItemSheets/AllItemSheetV1.mjs b/module/Apps/ItemSheets/AllItemSheetV1.mjs new file mode 100644 index 0000000..e8c2e03 --- /dev/null +++ b/module/Apps/ItemSheets/AllItemSheetV1.mjs @@ -0,0 +1,50 @@ +import { filePath } from "../../consts.mjs"; +import { GenericAppMixin } from "../GenericApp.mjs"; +import { Logger } from "../../utils/Logger.mjs"; + +const { HandlebarsApplicationMixin } = foundry.applications.api; +const { ItemSheetV2 } = foundry.applications.sheets; + +export class AllItemSheetV1 extends GenericAppMixin(HandlebarsApplicationMixin(ItemSheetV2)) { + + // #region Options + static DEFAULT_OPTIONS = { + classes: [ + `ripcrypt--item`, + `ripcrypt--AllItemSheetV1`, + ], + position: { + width: `auto`, + height: `auto`, + }, + window: { + resizable: false, + }, + actions: { + }, + form: { + submitOnChange: true, + closeOnSubmit: false, + }, + }; + + static PARTS = { + content: { + template: filePath(`templates/Apps/AllItemSheetV1/content.hbs`), + }, + }; + // #endregion + + // #region Lifecycle + async _preparePartContext(partId, ctx, opts) { + ctx = await super._preparePartContext(partId, ctx, opts); + ctx.actor = this.document; + + Logger.debug(`Context:`, ctx); + return ctx; + }; + // #endregion + + // #region Actions + // #endregion +}; diff --git a/module/hooks/init.mjs b/module/hooks/init.mjs index c5ad784..e76673f 100644 --- a/module/hooks/init.mjs +++ b/module/hooks/init.mjs @@ -1,4 +1,5 @@ // Applications +import { AllItemSheetV1 } from "../Apps/ItemSheets/AllItemSheetV1.mjs"; import { HeroSkillsCardV1 } from "../Apps/ActorSheets/HeroSkillsCardV1.mjs"; import { HeroSummaryCardV1 } from "../Apps/ActorSheets/HeroSummaryCardV1.mjs"; @@ -34,6 +35,12 @@ Hooks.once(`init`, () => { // #endregion // #region Sheets + // Unregister core sheets + /* eslint-disable no-undef */ + Items.unregisterSheet(`core`, ItemSheet); + Actors.unregisterSheet(`core`, ActorSheet); + /* eslint-enabled no-undef */ + // #region Actors Actors.registerSheet(game.system.id, HeroSummaryCardV1, { makeDefault: true, @@ -47,6 +54,14 @@ Hooks.once(`init`, () => { themes: HeroSkillsCardV1.themes, }); // #endregion + + // #region Items + Items.registerSheet(game.system.id, AllItemSheetV1, { + makeDefault: true, + label: `RipCrypt.sheet-names.AllItemsSheetV1`, + themes: AllItemSheetV1.themes, + }); + // #endregion // #endregion // #region Token Attrs diff --git a/templates/Apps/AllItemSheetV1/content.hbs b/templates/Apps/AllItemSheetV1/content.hbs new file mode 100644 index 0000000..43a098c --- /dev/null +++ b/templates/Apps/AllItemSheetV1/content.hbs @@ -0,0 +1,3 @@ +
+ All Item Sheet V1 +
diff --git a/templates/Apps/AllItemSheetV1/style.css b/templates/Apps/AllItemSheetV1/style.css new file mode 100644 index 0000000..8c2b98e --- /dev/null +++ b/templates/Apps/AllItemSheetV1/style.css @@ -0,0 +1,3 @@ +.ripcrypt .AllItemSheetV1 { + --input-height: 1rem; +} diff --git a/templates/Apps/apps.css b/templates/Apps/apps.css index 5fee16a..07bfaf1 100644 --- a/templates/Apps/apps.css +++ b/templates/Apps/apps.css @@ -1,2 +1,3 @@ +@import url("./AllItemSheetV1/style.css"); @import url("./HeroSummaryCardV1/style.css"); @import url("./HeroSkillsCardV1/style.css"); From 4b423a07299afaafd861e72e66d76a3c3b2c48ec Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Wed, 8 Jan 2025 21:53:09 -0700 Subject: [PATCH 005/246] RC-92 | Datamodel Defined Input Definition --- module/Apps/ItemSheets/AllItemSheetV1.mjs | 2 +- module/data/Item/Weapon.mjs | 19 ++++++++++++++++++ module/handlebarHelpers/_index.mjs | 2 ++ module/handlebarHelpers/inputs/formFields.mjs | 20 +++++++++++++++++++ templates/Apps/AllItemSheetV1/content.hbs | 2 +- 5 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 module/handlebarHelpers/inputs/formFields.mjs diff --git a/module/Apps/ItemSheets/AllItemSheetV1.mjs b/module/Apps/ItemSheets/AllItemSheetV1.mjs index e8c2e03..83aa9eb 100644 --- a/module/Apps/ItemSheets/AllItemSheetV1.mjs +++ b/module/Apps/ItemSheets/AllItemSheetV1.mjs @@ -38,7 +38,7 @@ export class AllItemSheetV1 extends GenericAppMixin(HandlebarsApplicationMixin(I // #region Lifecycle async _preparePartContext(partId, ctx, opts) { ctx = await super._preparePartContext(partId, ctx, opts); - ctx.actor = this.document; + ctx.item = this.document; Logger.debug(`Context:`, ctx); return ctx; diff --git a/module/data/Item/Weapon.mjs b/module/data/Item/Weapon.mjs index 2e42e35..1c16aa9 100644 --- a/module/data/Item/Weapon.mjs +++ b/module/data/Item/Weapon.mjs @@ -55,4 +55,23 @@ export class WeaponData extends foundry.abstract.TypeDataModel { return String(this.range.short ?? this.range.long ?? ``); } // #endregion + + // #region Sheet Data + get formFields() { + const fields = [ + { type: `set`, label: `Traits` }, + { type: `integer`, label: `Short Range` }, + { type: `integer`, label: `Long Range` }, + { type: `integer`, label: `Damage` }, + { type: `bar`, label: `Wear` }, + { type: `dropdown`, label: `Access` }, + ]; + + if (this.parent.isEmbedded) { + fields.push({ type: `boolean`, label: `Equipped` }); + }; + + return fields; + }; + // #endregion }; diff --git a/module/handlebarHelpers/_index.mjs b/module/handlebarHelpers/_index.mjs index 1603faf..9c8587d 100644 --- a/module/handlebarHelpers/_index.mjs +++ b/module/handlebarHelpers/_index.mjs @@ -1,8 +1,10 @@ import { handlebarsLocalizer, localizer } from "../utils/Localizer.mjs"; +import { formFields } from "./inputs/formFields.mjs"; import { options } from "./options.mjs"; export default { // #region Complex + "rc-formFields": formFields, "rc-i18n": handlebarsLocalizer, "rc-options": options, diff --git a/module/handlebarHelpers/inputs/formFields.mjs b/module/handlebarHelpers/inputs/formFields.mjs new file mode 100644 index 0000000..0ddd6b5 --- /dev/null +++ b/module/handlebarHelpers/inputs/formFields.mjs @@ -0,0 +1,20 @@ +const inputTypes = { + set: displayOnly, + integer: displayOnly, + bar: displayOnly, + dropdown: displayOnly, + boolean: displayOnly, +}; + +function displayOnly(input) { + return `
${input.label}
`; +}; + +export function formFields(inputs) { + let htmlString = ``; + for (const input of inputs) { + if (inputTypes[input.type] == null) { continue }; + htmlString += inputTypes[input.type](input); + }; + return htmlString; +}; diff --git a/templates/Apps/AllItemSheetV1/content.hbs b/templates/Apps/AllItemSheetV1/content.hbs index 43a098c..3d48a8e 100644 --- a/templates/Apps/AllItemSheetV1/content.hbs +++ b/templates/Apps/AllItemSheetV1/content.hbs @@ -1,3 +1,3 @@
- All Item Sheet V1 + {{{ rc-formFields item.system.formFields }}}
From d0374880bc95d99095c82bb13994d7abf16bd97f Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Thu, 9 Jan 2025 23:53:53 -0700 Subject: [PATCH 006/246] RC-82 | Name Input --- module/Apps/ItemSheets/AllItemSheetV1.mjs | 2 ++ module/data/Item/Weapon.mjs | 2 +- templates/Apps/AllItemSheetV1/content.hbs | 16 ++++++++++++- templates/Apps/AllItemSheetV1/style.css | 28 +++++++++++++++++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/module/Apps/ItemSheets/AllItemSheetV1.mjs b/module/Apps/ItemSheets/AllItemSheetV1.mjs index 83aa9eb..900cd35 100644 --- a/module/Apps/ItemSheets/AllItemSheetV1.mjs +++ b/module/Apps/ItemSheets/AllItemSheetV1.mjs @@ -40,6 +40,8 @@ export class AllItemSheetV1 extends GenericAppMixin(HandlebarsApplicationMixin(I ctx = await super._preparePartContext(partId, ctx, opts); ctx.item = this.document; + ctx.formFields = this.document.system.getFormFields(ctx); + Logger.debug(`Context:`, ctx); return ctx; }; diff --git a/module/data/Item/Weapon.mjs b/module/data/Item/Weapon.mjs index 1c16aa9..06460f9 100644 --- a/module/data/Item/Weapon.mjs +++ b/module/data/Item/Weapon.mjs @@ -57,7 +57,7 @@ export class WeaponData extends foundry.abstract.TypeDataModel { // #endregion // #region Sheet Data - get formFields() { + getFormFields(ctx) { const fields = [ { type: `set`, label: `Traits` }, { type: `integer`, label: `Short Range` }, diff --git a/templates/Apps/AllItemSheetV1/content.hbs b/templates/Apps/AllItemSheetV1/content.hbs index 3d48a8e..3490868 100644 --- a/templates/Apps/AllItemSheetV1/content.hbs +++ b/templates/Apps/AllItemSheetV1/content.hbs @@ -1,3 +1,17 @@
- {{{ rc-formFields item.system.formFields }}} +
+ {{#if meta.editable}} + + + {{else}} + Name + {{item.name}} + {{/if}} +
+ {{{ rc-formFields formFields }}}
diff --git a/templates/Apps/AllItemSheetV1/style.css b/templates/Apps/AllItemSheetV1/style.css index 8c2b98e..aae921a 100644 --- a/templates/Apps/AllItemSheetV1/style.css +++ b/templates/Apps/AllItemSheetV1/style.css @@ -1,3 +1,31 @@ .ripcrypt .AllItemSheetV1 { --input-height: 1rem; + --col-gap: 8px; + + display: grid; + grid-template-rows: minmax(0, 1fr); + grid-auto-rows: minmax(0, 1fr); + column-gap: var(--col-gap); + + background: var(--base-background); + color: var(--base-text); + + > :nth-child(odd) { + background: var(--alt-row-background); + color: var(--alt-row-text); + } + + label, .label { + box-sizing: border-box; + padding: 2px 4px; + text-transform: uppercase; + font-size: var(--font-size-14); + overflow: hidden; + text-overflow: ellipsis; + font-weight: bold; + } + + .input-group { + display: contents; + } } From 000f4905844775a8286e34398c0afcd1d9c66cff Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Fri, 10 Jan 2025 00:54:16 -0700 Subject: [PATCH 007/246] RC-88 | String Set Input --- module/data/Item/Weapon.mjs | 7 ++++- module/handlebarHelpers/inputs/formFields.mjs | 8 ++++-- module/handlebarHelpers/inputs/string-set.mjs | 25 +++++++++++++++++ templates/Apps/AllItemSheetV1/style.css | 22 +++++++++++++-- templates/css/common.css | 1 + templates/css/elements/string-tags.css | 28 +++++++++++++++++++ templates/css/themes/dark.css | 10 +++++++ 7 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 module/handlebarHelpers/inputs/string-set.mjs create mode 100644 templates/css/elements/string-tags.css diff --git a/module/data/Item/Weapon.mjs b/module/data/Item/Weapon.mjs index 06460f9..dd23042 100644 --- a/module/data/Item/Weapon.mjs +++ b/module/data/Item/Weapon.mjs @@ -59,7 +59,12 @@ export class WeaponData extends foundry.abstract.TypeDataModel { // #region Sheet Data getFormFields(ctx) { const fields = [ - { type: `set`, label: `Traits` }, + { + type: `string-set`, + label: `RipCrypt.common.traits`, + path: `system.traits`, + value: this.traitString, + }, { type: `integer`, label: `Short Range` }, { type: `integer`, label: `Long Range` }, { type: `integer`, label: `Damage` }, diff --git a/module/handlebarHelpers/inputs/formFields.mjs b/module/handlebarHelpers/inputs/formFields.mjs index 0ddd6b5..16ca51e 100644 --- a/module/handlebarHelpers/inputs/formFields.mjs +++ b/module/handlebarHelpers/inputs/formFields.mjs @@ -1,5 +1,7 @@ +import { stringSet } from "./string-set.mjs"; + const inputTypes = { - set: displayOnly, + "string-set": stringSet, integer: displayOnly, bar: displayOnly, dropdown: displayOnly, @@ -10,11 +12,11 @@ function displayOnly(input) { return `
${input.label}
`; }; -export function formFields(inputs) { +export function formFields(inputs, opts) { let htmlString = ``; for (const input of inputs) { if (inputTypes[input.type] == null) { continue }; - htmlString += inputTypes[input.type](input); + htmlString += inputTypes[input.type](input, opts.data.root); }; return htmlString; }; diff --git a/module/handlebarHelpers/inputs/string-set.mjs b/module/handlebarHelpers/inputs/string-set.mjs new file mode 100644 index 0000000..c8dfe76 --- /dev/null +++ b/module/handlebarHelpers/inputs/string-set.mjs @@ -0,0 +1,25 @@ +import { localizer } from "../../utils/Localizer.mjs"; + +export function stringSet(input, data) { + const label = localizer(input.label); + + if (!data.meta.editable) { + return `
+ ${label} + ${input.value} +
`; + }; + + return `
+ + +
`; +}; diff --git a/templates/Apps/AllItemSheetV1/style.css b/templates/Apps/AllItemSheetV1/style.css index aae921a..8e73f7b 100644 --- a/templates/Apps/AllItemSheetV1/style.css +++ b/templates/Apps/AllItemSheetV1/style.css @@ -2,6 +2,11 @@ --input-height: 1rem; --col-gap: 8px; + --string-tags-tag-text: var(--header-text); + --string-tags-tag-background: var(--header-background); + --string-tags-add-text: white; + --string-tags-add-background: var(--accent-1); + display: grid; grid-template-rows: minmax(0, 1fr); grid-auto-rows: minmax(0, 1fr); @@ -13,6 +18,11 @@ > :nth-child(odd) { background: var(--alt-row-background); color: var(--alt-row-text); + + --string-tags-tag-text: var(--header-text); + --string-tags-tag-background: var(--header-background); + --string-tags-add-text: var(--button-text); + --string-tags-add-background: var(--button-background); } label, .label { @@ -25,7 +35,15 @@ font-weight: bold; } - .input-group { - display: contents; + [data-input-type="string-set"] { + padding: 2px 4px; + display: flex; + flex-direction: row; + column-gap: var(--col-gap); + grid-row: span 2; + + label, .label { + padding: 0; + } } } diff --git a/templates/css/common.css b/templates/css/common.css index 175d7a9..d234f59 100644 --- a/templates/css/common.css +++ b/templates/css/common.css @@ -5,6 +5,7 @@ @import url("./elements/lists.css"); @import url("./elements/select.css"); @import url("./elements/span.css"); +@import url("./elements/string-tags.css"); @import url("./elements/table.css"); .ripcrypt { diff --git a/templates/css/elements/string-tags.css b/templates/css/elements/string-tags.css new file mode 100644 index 0000000..bd1bc31 --- /dev/null +++ b/templates/css/elements/string-tags.css @@ -0,0 +1,28 @@ +.ripcrypt string-tags { + --input-background: var(--string-tags-input-background); + + display: grid; + grid-template-columns: 1fr min-content; + grid-template-rows: repeat(2, minmax(0, 1fr)); + + padding: 2px; + border: var(--string-tags-border); + + .tags { + grid-column: 1 / -1; + } + + .tag { + background: var(--tag-background, var(--header-background)); + color: var(--tag-text, var(--header-text)); + padding: 2px 4px; + } + + button.icon.icon { + font-family: var(--font-awesome); + background: var(--string-tags-add-background); + color: var(--string-tags-add-text); + width: 30px; + border-radius: 4px; + } +} diff --git a/templates/css/themes/dark.css b/templates/css/themes/dark.css index 9c0c05d..1f92f66 100644 --- a/templates/css/themes/dark.css +++ b/templates/css/themes/dark.css @@ -7,6 +7,9 @@ --base-text: white; --base-background: black; + --header-text: black; + --header-background: var(--accent-3); + --section-header-text: white; --section-header-background: var(--accent-1); @@ -19,4 +22,11 @@ --button-background: black; --button-text: var(--accent-3); + + /* Additional Variables */ + --string-tags-border: inherit; + --string-tags-tag-background: inherit; + --string-tags-tag-text: inherit; + --string-tags-add-background: inherit; + --string-tags-add-text: var(--accent-3); } From ea014fee1027f40a7e2a926da893cb520b37ae61 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Fri, 10 Jan 2025 18:23:01 -0700 Subject: [PATCH 008/246] Rename file --- module/handlebarHelpers/inputs/formFields.mjs | 2 +- .../handlebarHelpers/inputs/{string-set.mjs => stringSet.mjs} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename module/handlebarHelpers/inputs/{string-set.mjs => stringSet.mjs} (100%) diff --git a/module/handlebarHelpers/inputs/formFields.mjs b/module/handlebarHelpers/inputs/formFields.mjs index 16ca51e..3d13129 100644 --- a/module/handlebarHelpers/inputs/formFields.mjs +++ b/module/handlebarHelpers/inputs/formFields.mjs @@ -1,4 +1,4 @@ -import { stringSet } from "./string-set.mjs"; +import { stringSet } from "./stringSet.mjs"; const inputTypes = { "string-set": stringSet, diff --git a/module/handlebarHelpers/inputs/string-set.mjs b/module/handlebarHelpers/inputs/stringSet.mjs similarity index 100% rename from module/handlebarHelpers/inputs/string-set.mjs rename to module/handlebarHelpers/inputs/stringSet.mjs From 5aee7e4a295aa1053420494862396935bf140809 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Fri, 10 Jan 2025 18:41:03 -0700 Subject: [PATCH 009/246] Prevent duplicate IDs --- module/handlebarHelpers/inputs/stringSet.mjs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/module/handlebarHelpers/inputs/stringSet.mjs b/module/handlebarHelpers/inputs/stringSet.mjs index c8dfe76..3932a1b 100644 --- a/module/handlebarHelpers/inputs/stringSet.mjs +++ b/module/handlebarHelpers/inputs/stringSet.mjs @@ -1,7 +1,10 @@ import { localizer } from "../../utils/Localizer.mjs"; +const { randomID } = foundry.utils; + export function stringSet(input, data) { const label = localizer(input.label); + const id = `${data.meta.idp}-${randomID(10)}`; if (!data.meta.editable) { return `
@@ -12,12 +15,12 @@ export function stringSet(input, data) { return `
From fb52e1b58d121f6c3f4133e3bb30cecfac685e37 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Sat, 11 Jan 2025 17:35:17 -0700 Subject: [PATCH 010/246] Add number inputs into the supported structures, and redesign the sheet to make it actually look good --- langs/en-ca.json | 5 +- module/data/Item/Weapon.mjs | 31 +++++++++--- module/handlebarHelpers/inputs/formFields.mjs | 9 ++-- .../handlebarHelpers/inputs/numberInput.mjs | 35 ++++++++++++++ module/handlebarHelpers/inputs/stringSet.mjs | 25 +++++++++- templates/Apps/AllItemSheetV1/content.hbs | 28 +++++------ templates/Apps/AllItemSheetV1/style.css | 48 ++++++++++++------- templates/css/elements/input.css | 4 ++ templates/css/elements/span.css | 4 ++ templates/css/elements/string-tags.css | 16 +++++-- templates/css/themes/dark.css | 4 ++ 11 files changed, 161 insertions(+), 48 deletions(-) create mode 100644 module/handlebarHelpers/inputs/numberInput.mjs diff --git a/langs/en-ca.json b/langs/en-ca.json index 5103805..abb3e88 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -74,7 +74,10 @@ "guts-value-edit": "The current amount of guts the character has", "guts-value-readonly": "The current amount of guts the character has", "guts-max-readonly": "The maximum amount of guts the character can have" - } + }, + "traits-placeholder": "New Trait...", + "short-range": "Short @RipCrypt.common.range", + "long-range": "Long @RipCrypt.common.range" } } } diff --git a/module/data/Item/Weapon.mjs b/module/data/Item/Weapon.mjs index dd23042..f269961 100644 --- a/module/data/Item/Weapon.mjs +++ b/module/data/Item/Weapon.mjs @@ -62,14 +62,33 @@ export class WeaponData extends foundry.abstract.TypeDataModel { { type: `string-set`, label: `RipCrypt.common.traits`, + placeholder: `RipCrypt.Apps.traits-placeholder`, path: `system.traits`, - value: this.traitString, + value: ctx.meta.limited ? `???` : this.traitString, }, - { type: `integer`, label: `Short Range` }, - { type: `integer`, label: `Long Range` }, - { type: `integer`, label: `Damage` }, - { type: `bar`, label: `Wear` }, - { type: `dropdown`, label: `Access` }, + { + type: `integer`, + label: `RipCrypt.Apps.short-range`, + path: `system.range.short`, + value: ctx.meta.limited ? `???` : (this.range.short ?? ``), + min: 0, + }, + { + type: `integer`, + label: `RipCrypt.Apps.long-range`, + path: `system.range.long`, + value: ctx.meta.limited ? `???` : (this.range.long ?? ``), + min: 0, + }, + { + type: `integer`, + label: `RipCrypt.common.damage`, + path: `system.damage`, + value: ctx.meta.limited ? `???` : this.damage, + min: 0, + }, + // { type: `bar`, label: `Wear` }, + // { type: `dropdown`, label: `Access` }, ]; if (this.parent.isEmbedded) { diff --git a/module/handlebarHelpers/inputs/formFields.mjs b/module/handlebarHelpers/inputs/formFields.mjs index 3d13129..cd081f0 100644 --- a/module/handlebarHelpers/inputs/formFields.mjs +++ b/module/handlebarHelpers/inputs/formFields.mjs @@ -1,8 +1,9 @@ +import { numberInput } from "./numberInput.mjs"; import { stringSet } from "./stringSet.mjs"; const inputTypes = { "string-set": stringSet, - integer: displayOnly, + integer: numberInput, bar: displayOnly, dropdown: displayOnly, boolean: displayOnly, @@ -13,10 +14,10 @@ function displayOnly(input) { }; export function formFields(inputs, opts) { - let htmlString = ``; + const fields = []; for (const input of inputs) { if (inputTypes[input.type] == null) { continue }; - htmlString += inputTypes[input.type](input, opts.data.root); + fields.push(inputTypes[input.type](input, opts.data.root)); }; - return htmlString; + return fields.join(opts.hash?.joiner ?? `
`); }; diff --git a/module/handlebarHelpers/inputs/numberInput.mjs b/module/handlebarHelpers/inputs/numberInput.mjs new file mode 100644 index 0000000..3cc15eb --- /dev/null +++ b/module/handlebarHelpers/inputs/numberInput.mjs @@ -0,0 +1,35 @@ +import { localizer } from "../../utils/Localizer.mjs"; + +const { randomID } = foundry.utils; + +export function numberInput(input, data) { + const label = localizer(input.label); + const id = `${data.meta.idp}-${randomID(10)}`; + + if (!data.meta.editable) { + return `
+ ${label} + ${data.meta.limited ? `???` : input.value} +
`; + }; + + let attrs = ``; + if (input.min) { attrs += ` min="${input.min}"` }; + if (input.max) { attrs += ` max="${input.max}"` }; + if (input.step) { attrs += `step="${input.step}"` }; + + return `
+ + +
`; +}; diff --git a/module/handlebarHelpers/inputs/stringSet.mjs b/module/handlebarHelpers/inputs/stringSet.mjs index 3932a1b..3b4a604 100644 --- a/module/handlebarHelpers/inputs/stringSet.mjs +++ b/module/handlebarHelpers/inputs/stringSet.mjs @@ -4,12 +4,34 @@ const { randomID } = foundry.utils; export function stringSet(input, data) { const label = localizer(input.label); + const placeholder = localizer(input.placeholder ?? ``); const id = `${data.meta.idp}-${randomID(10)}`; if (!data.meta.editable) { + const tagList = input.value + .split(/,\s*/) + .filter(t => t.length > 0) + .map(t => { + return `
${t.trim()}
`; + }); + let tags = tagList.join(``); + + if (tagList.length === 0) { + tags = `---`; + }; + + if (data.meta.limited) { + tags = `???`; + }; + return `
${label} - ${input.value} +
+ ${tags} +
`; }; @@ -21,6 +43,7 @@ export function stringSet(input, data) { diff --git a/templates/Apps/AllItemSheetV1/content.hbs b/templates/Apps/AllItemSheetV1/content.hbs index 3490868..0fb9599 100644 --- a/templates/Apps/AllItemSheetV1/content.hbs +++ b/templates/Apps/AllItemSheetV1/content.hbs @@ -1,17 +1,17 @@
-
- {{#if meta.editable}} - - - {{else}} - Name - {{item.name}} - {{/if}} -
+ {{#if meta.editable}} + + + {{else}} + Name + {{item.name}} + {{/if}} +
{{{ rc-formFields formFields }}}
diff --git a/templates/Apps/AllItemSheetV1/style.css b/templates/Apps/AllItemSheetV1/style.css index 8e73f7b..549fdcd 100644 --- a/templates/Apps/AllItemSheetV1/style.css +++ b/templates/Apps/AllItemSheetV1/style.css @@ -1,32 +1,42 @@ .ripcrypt .AllItemSheetV1 { --input-height: 1rem; + --input-underline: none; --col-gap: 8px; + --row-gap: 8px; --string-tags-tag-text: var(--header-text); --string-tags-tag-background: var(--header-background); --string-tags-add-text: white; --string-tags-add-background: var(--accent-1); + --string-tags-input-text: white; + --string-tags-input-background: var(--accent-1); display: grid; - grid-template-rows: minmax(0, 1fr); - grid-auto-rows: minmax(0, 1fr); + grid-template-columns: auto minmax(0, 1fr); column-gap: var(--col-gap); + row-gap: var(--row-gap); + padding: 8px; background: var(--base-background); color: var(--base-text); - > :nth-child(odd) { - background: var(--alt-row-background); - color: var(--alt-row-text); + > [data-input-type] { + display: contents; + } - --string-tags-tag-text: var(--header-text); - --string-tags-tag-background: var(--header-background); - --string-tags-add-text: var(--button-text); - --string-tags-add-background: var(--button-background); + hr { + background: var(--accent-1); + grid-column: 1 / -1; + height: 1px; + width: 90%; + margin: 0 auto; } label, .label { + display: flex; + align-items: center; box-sizing: border-box; + padding: 2px 4px; text-transform: uppercase; font-size: var(--font-size-14); @@ -35,15 +45,17 @@ font-weight: bold; } - [data-input-type="string-set"] { + input, .value, [data-tag-count] { + border-radius: 4px; padding: 2px 4px; - display: flex; - flex-direction: row; - column-gap: var(--col-gap); - grid-row: span 2; - - label, .label { - padding: 0; - } + } + input { + background: var(--accent-2); + } + .value, [data-tag-count="0"] { + border: 2px solid var(--accent-2); + } + [data-tag-count="0"] { + justify-content: start; } } diff --git a/templates/css/elements/input.css b/templates/css/elements/input.css index 0ab1fa0..c800d7c 100644 --- a/templates/css/elements/input.css +++ b/templates/css/elements/input.css @@ -15,5 +15,9 @@ &[type="number"] { border-bottom: var(--input-underline); } + + &::placeholder { + color: var(--input-placeholder-text); + } } } diff --git a/templates/css/elements/span.css b/templates/css/elements/span.css index ac5b330..65a1858 100644 --- a/templates/css/elements/span.css +++ b/templates/css/elements/span.css @@ -2,4 +2,8 @@ &.small { font-size: var(--font-size-10) } + + &:empty::before { + content: "\200b"; + } } diff --git a/templates/css/elements/string-tags.css b/templates/css/elements/string-tags.css index bd1bc31..1998c00 100644 --- a/templates/css/elements/string-tags.css +++ b/templates/css/elements/string-tags.css @@ -5,16 +5,14 @@ grid-template-columns: 1fr min-content; grid-template-rows: repeat(2, minmax(0, 1fr)); - padding: 2px; border: var(--string-tags-border); .tags { grid-column: 1 / -1; } - .tag { - background: var(--tag-background, var(--header-background)); - color: var(--tag-text, var(--header-text)); + input[type="text"] { + border-radius: 4px; padding: 2px 4px; } @@ -25,4 +23,14 @@ width: 30px; border-radius: 4px; } + + &:has(.tags.input-element-tags:empty) { + grid-template-rows: auto; + } +} + +.ripcrypt .tag { + background: var(--tag-background, var(--header-background)); + color: var(--tag-text, var(--header-text)); + padding: 2px 4px; } diff --git a/templates/css/themes/dark.css b/templates/css/themes/dark.css index 1f92f66..7fea063 100644 --- a/templates/css/themes/dark.css +++ b/templates/css/themes/dark.css @@ -19,10 +19,14 @@ --input-underline: 2px dashed var(--accent-3); --input-background: inherit; --input-text: white; + --input-placeholder-text: rgba(255,255,255, 0.5); --button-background: black; --button-text: var(--accent-3); + --col-gap: 2px; + --row-gap: 0px; + /* Additional Variables */ --string-tags-border: inherit; --string-tags-tag-background: inherit; From 8d920402308b3e7db4442ef6476fdc49cb24128e Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Sat, 11 Jan 2025 20:04:27 -0700 Subject: [PATCH 011/246] RC-91 | Add dropdown option support --- langs/en-ca.json | 8 +++- module/data/Item/Weapon.mjs | 25 +++++++++--- .../handlebarHelpers/inputs/dropdownInput.mjs | 38 +++++++++++++++++++ module/handlebarHelpers/inputs/formFields.mjs | 4 +- templates/Apps/AllItemSheetV1/style.css | 10 ++--- templates/css/elements/select.css | 3 ++ 6 files changed, 76 insertions(+), 12 deletions(-) create mode 100644 module/handlebarHelpers/inputs/dropdownInput.mjs diff --git a/langs/en-ca.json b/langs/en-ca.json index abb3e88..b47708c 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -55,7 +55,13 @@ "arms": "Arms", "legs": "Legs" }, - "shield": "Shield" + "shield": "Shield", + "access": { + "Common": "Common", + "Uncommon": "Uncommon", + "Rare": "Rare", + "Scarce": "Scarce" + } }, "setting": { "abbrAccess": { diff --git a/module/data/Item/Weapon.mjs b/module/data/Item/Weapon.mjs index f269961..ff28d88 100644 --- a/module/data/Item/Weapon.mjs +++ b/module/data/Item/Weapon.mjs @@ -64,31 +64,46 @@ export class WeaponData extends foundry.abstract.TypeDataModel { label: `RipCrypt.common.traits`, placeholder: `RipCrypt.Apps.traits-placeholder`, path: `system.traits`, - value: ctx.meta.limited ? `???` : this.traitString, + value: this.traitString, }, { type: `integer`, label: `RipCrypt.Apps.short-range`, path: `system.range.short`, - value: ctx.meta.limited ? `???` : (this.range.short ?? ``), + value: this.range.short ?? ``, min: 0, }, { type: `integer`, label: `RipCrypt.Apps.long-range`, path: `system.range.long`, - value: ctx.meta.limited ? `???` : (this.range.long ?? ``), + value: this.range.long ?? ``, min: 0, }, { type: `integer`, label: `RipCrypt.common.damage`, path: `system.damage`, - value: ctx.meta.limited ? `???` : this.damage, + value: this.damage, min: 0, }, // { type: `bar`, label: `Wear` }, - // { type: `dropdown`, label: `Access` }, + { + type: `dropdown`, + label: `Access`, + path: `system.access`, + value: this.access, + options: [ + { + label: `RipCrypt.common.empty`, + value: ``, + }, + ...gameTerms.Access.map(opt => ({ + label: `RipCrypt.common.access.${opt}`, + value: opt, + })), + ], + }, ]; if (this.parent.isEmbedded) { diff --git a/module/handlebarHelpers/inputs/dropdownInput.mjs b/module/handlebarHelpers/inputs/dropdownInput.mjs new file mode 100644 index 0000000..3b4d10d --- /dev/null +++ b/module/handlebarHelpers/inputs/dropdownInput.mjs @@ -0,0 +1,38 @@ +import { localizer } from "../../utils/Localizer.mjs"; +import { options } from "../options.mjs"; + +const { randomID } = foundry.utils; + +export function dropdownInput(input, data) { + const label = localizer(input.label); + const id = `${data.meta.idp}-${randomID(10)}`; + + if (!data.meta.editable) { + return `
+ ${label} + ${data.meta.limited ? `???` : input.value} +
`; + }; + + if (!input.options.length) { + throw new Error(`dropdown type inputs must have some options`); + }; + + return `
+ + +
`; +}; diff --git a/module/handlebarHelpers/inputs/formFields.mjs b/module/handlebarHelpers/inputs/formFields.mjs index cd081f0..3268d79 100644 --- a/module/handlebarHelpers/inputs/formFields.mjs +++ b/module/handlebarHelpers/inputs/formFields.mjs @@ -1,3 +1,4 @@ +import { dropdownInput } from "./dropdownInput.mjs"; import { numberInput } from "./numberInput.mjs"; import { stringSet } from "./stringSet.mjs"; @@ -5,7 +6,7 @@ const inputTypes = { "string-set": stringSet, integer: numberInput, bar: displayOnly, - dropdown: displayOnly, + dropdown: dropdownInput, boolean: displayOnly, }; @@ -17,6 +18,7 @@ export function formFields(inputs, opts) { const fields = []; for (const input of inputs) { if (inputTypes[input.type] == null) { continue }; + input.value = Handlebars.escapeExpression(input.value); fields.push(inputTypes[input.type](input, opts.data.root)); }; return fields.join(opts.hash?.joiner ?? `
`); diff --git a/templates/Apps/AllItemSheetV1/style.css b/templates/Apps/AllItemSheetV1/style.css index 549fdcd..a90fd1e 100644 --- a/templates/Apps/AllItemSheetV1/style.css +++ b/templates/Apps/AllItemSheetV1/style.css @@ -9,7 +9,10 @@ --string-tags-add-text: white; --string-tags-add-background: var(--accent-1); --string-tags-input-text: white; - --string-tags-input-background: var(--accent-1); + --string-tags-input-background: var(--accent-2); + + --input-text: white; + --input-background: var(--accent-2); display: grid; grid-template-columns: auto minmax(0, 1fr); @@ -45,13 +48,10 @@ font-weight: bold; } - input, .value, [data-tag-count] { + input, select, .value, [data-tag-count] { border-radius: 4px; padding: 2px 4px; } - input { - background: var(--accent-2); - } .value, [data-tag-count="0"] { border: 2px solid var(--accent-2); } diff --git a/templates/css/elements/select.css b/templates/css/elements/select.css index 2ea8495..b822816 100644 --- a/templates/css/elements/select.css +++ b/templates/css/elements/select.css @@ -8,4 +8,7 @@ font-size: inherit; display: flex; align-items: center; + + background: var(--input-background); + color: var(--input-text); } From 5c78523791fdc1c9d12505ba1d3cfadcd77cbdd4 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Sun, 12 Jan 2025 00:19:39 -0700 Subject: [PATCH 012/246] RC-90 | Add support for bar-input controls in item sheets --- langs/en-ca.json | 4 +- module/data/Item/Weapon.mjs | 18 ++++++- module/handlebarHelpers/inputs/barInput.mjs | 36 ++++++++++++++ .../handlebarHelpers/inputs/dropdownInput.mjs | 2 +- module/handlebarHelpers/inputs/formFields.mjs | 18 +++++-- .../handlebarHelpers/inputs/numberInput.mjs | 2 +- module/handlebarHelpers/inputs/stringSet.mjs | 8 ++-- templates/Apps/AllItemSheetV1/style.css | 5 +- templates/css/common.css | 1 + templates/css/elements/pill-bar.css | 47 +++++++++++++++++++ templates/css/elements/string-tags.css | 4 +- templates/css/themes/dark.css | 8 ++++ 12 files changed, 140 insertions(+), 13 deletions(-) create mode 100644 module/handlebarHelpers/inputs/barInput.mjs create mode 100644 templates/css/elements/pill-bar.css diff --git a/langs/en-ca.json b/langs/en-ca.json index b47708c..c496c58 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -83,7 +83,9 @@ }, "traits-placeholder": "New Trait...", "short-range": "Short @RipCrypt.common.range", - "long-range": "Long @RipCrypt.common.range" + "long-range": "Long @RipCrypt.common.range", + "current-wear": "Current @RipCrypt.common.wear", + "max-wear": "Maximum @RipCrypt.common.wear" } } } diff --git a/module/data/Item/Weapon.mjs b/module/data/Item/Weapon.mjs index ff28d88..a2ec6b7 100644 --- a/module/data/Item/Weapon.mjs +++ b/module/data/Item/Weapon.mjs @@ -87,12 +87,28 @@ export class WeaponData extends foundry.abstract.TypeDataModel { value: this.damage, min: 0, }, - // { type: `bar`, label: `Wear` }, + { + type: `bar`, + label: `RipCrypt.common.wear`, + value: { + label: `RipCrypt.Apps.current-wear`, + path: `system.wear.value`, + value: this.wear.value, + min: 0, max: this.wear.max, + }, + max: { + label: `RipCrypt.Apps.max-wear`, + path: `system.wear.max`, + value: this.wear.max, + min: 0, + }, + }, { type: `dropdown`, label: `Access`, path: `system.access`, value: this.access, + limited: false, options: [ { label: `RipCrypt.common.empty`, diff --git a/module/handlebarHelpers/inputs/barInput.mjs b/module/handlebarHelpers/inputs/barInput.mjs new file mode 100644 index 0000000..f72983e --- /dev/null +++ b/module/handlebarHelpers/inputs/barInput.mjs @@ -0,0 +1,36 @@ +import { localizer } from "../../utils/Localizer.mjs"; + +export function barInput(input, data) { + const label = localizer(input.label); + + // Trying to do limited bar info is... annoying to do. + if (data.meta.limited && input.limited) { + return ``; + }; + + return `
+ +
+ + +
+
`; +}; diff --git a/module/handlebarHelpers/inputs/dropdownInput.mjs b/module/handlebarHelpers/inputs/dropdownInput.mjs index 3b4d10d..142a9b1 100644 --- a/module/handlebarHelpers/inputs/dropdownInput.mjs +++ b/module/handlebarHelpers/inputs/dropdownInput.mjs @@ -10,7 +10,7 @@ export function dropdownInput(input, data) { if (!data.meta.editable) { return `
${label} - ${data.meta.limited ? `???` : input.value} + ${data.meta.limited && input.limited ? `???` : input.value}
`; }; diff --git a/module/handlebarHelpers/inputs/formFields.mjs b/module/handlebarHelpers/inputs/formFields.mjs index 3268d79..9b70d55 100644 --- a/module/handlebarHelpers/inputs/formFields.mjs +++ b/module/handlebarHelpers/inputs/formFields.mjs @@ -1,15 +1,20 @@ +import { barInput } from "./barInput.mjs"; import { dropdownInput } from "./dropdownInput.mjs"; import { numberInput } from "./numberInput.mjs"; import { stringSet } from "./stringSet.mjs"; +const { getType } = foundry.utils; + const inputTypes = { "string-set": stringSet, integer: numberInput, - bar: displayOnly, + bar: barInput, dropdown: dropdownInput, boolean: displayOnly, }; +const typesToSanitize = new Set([ `string`, `number` ]); + function displayOnly(input) { return `
${input.label}
`; }; @@ -18,8 +23,15 @@ export function formFields(inputs, opts) { const fields = []; for (const input of inputs) { if (inputTypes[input.type] == null) { continue }; - input.value = Handlebars.escapeExpression(input.value); + + input.limited ??= true; + + if (typesToSanitize.has(getType(input.value))) { + input.value = Handlebars.escapeExpression(input.value); + }; fields.push(inputTypes[input.type](input, opts.data.root)); }; - return fields.join(opts.hash?.joiner ?? `
`); + return fields + .filter(i => i.length > 0) + .join(opts.hash?.joiner ?? `
`); }; diff --git a/module/handlebarHelpers/inputs/numberInput.mjs b/module/handlebarHelpers/inputs/numberInput.mjs index 3cc15eb..9da389b 100644 --- a/module/handlebarHelpers/inputs/numberInput.mjs +++ b/module/handlebarHelpers/inputs/numberInput.mjs @@ -9,7 +9,7 @@ export function numberInput(input, data) { if (!data.meta.editable) { return `
${label} - ${data.meta.limited ? `???` : input.value} + ${data.meta.limited && input.limited ? `???` : input.value}
`; }; diff --git a/module/handlebarHelpers/inputs/stringSet.mjs b/module/handlebarHelpers/inputs/stringSet.mjs index 3b4a604..086cd61 100644 --- a/module/handlebarHelpers/inputs/stringSet.mjs +++ b/module/handlebarHelpers/inputs/stringSet.mjs @@ -14,21 +14,23 @@ export function stringSet(input, data) { .map(t => { return `
${t.trim()}
`; }); + let count = tagList.length; let tags = tagList.join(``); if (tagList.length === 0) { tags = `---`; }; - if (data.meta.limited) { + if (data.meta.limited && input.limited) { + count = 0; tags = `???`; }; return `
${label}
${tags}
diff --git a/templates/Apps/AllItemSheetV1/style.css b/templates/Apps/AllItemSheetV1/style.css index a90fd1e..247101c 100644 --- a/templates/Apps/AllItemSheetV1/style.css +++ b/templates/Apps/AllItemSheetV1/style.css @@ -14,8 +14,11 @@ --input-text: white; --input-background: var(--accent-2); + --pill-width: 100%; + --pill-border-radius: 4px; + display: grid; - grid-template-columns: auto minmax(0, 1fr); + grid-template-columns: auto 200px; column-gap: var(--col-gap); row-gap: var(--row-gap); diff --git a/templates/css/common.css b/templates/css/common.css index d234f59..7887a0f 100644 --- a/templates/css/common.css +++ b/templates/css/common.css @@ -3,6 +3,7 @@ @import url("./elements/button.css"); @import url("./elements/input.css"); @import url("./elements/lists.css"); +@import url("./elements/pill-bar.css"); @import url("./elements/select.css"); @import url("./elements/span.css"); @import url("./elements/string-tags.css"); diff --git a/templates/css/elements/pill-bar.css b/templates/css/elements/pill-bar.css new file mode 100644 index 0000000..e80537f --- /dev/null +++ b/templates/css/elements/pill-bar.css @@ -0,0 +1,47 @@ +.ripcrypt > .window-content .pill-bar { + display: flex; + flex-direction: row; + width: var(--pill-width, 100px); + border: 2px solid var(--pill-border); + border-radius: var(--pill-border-radius, 999px); + background: var(--pill-background); + align-items: center; + gap: 8px; + + > input { + color: var(--pill-input-text); + background: var(--pill-input-background); + border-radius: var(--pill-border-radius, 999px); + flex-shrink: 1; + flex-grow: 1; + min-width: 50px; + max-width: unset; + width: initial; + flex-basis: 50px; + text-align: center; + + &:disabled { + color: var(--pill-input-disabled-text); + background: var(--pill-input-disabled-background); + } + } + + > :first-child { + order: 1; + } + > :last-child { + order: 3; + } + + &::after { + display: block; + content: ""; + order: 1; + position: relative; + width: 2px; + height: 75%; + transform: rotate(30deg); + background: var(--pill-divider, var(--pill-border)); + z-index: 1; + } +} \ No newline at end of file diff --git a/templates/css/elements/string-tags.css b/templates/css/elements/string-tags.css index 1998c00..1099982 100644 --- a/templates/css/elements/string-tags.css +++ b/templates/css/elements/string-tags.css @@ -2,8 +2,8 @@ --input-background: var(--string-tags-input-background); display: grid; - grid-template-columns: 1fr min-content; - grid-template-rows: repeat(2, minmax(0, 1fr)); + grid-template-columns: minmax(0, 1fr) min-content; + grid-template-rows: repeat(2, min-content); border: var(--string-tags-border); diff --git a/templates/css/themes/dark.css b/templates/css/themes/dark.css index 7fea063..4809332 100644 --- a/templates/css/themes/dark.css +++ b/templates/css/themes/dark.css @@ -33,4 +33,12 @@ --string-tags-tag-text: inherit; --string-tags-add-background: inherit; --string-tags-add-text: var(--accent-3); + + --pill-border: var(--accent-2); + --pill-background: var(--accent-2); + --pill-divider: var(--accent-3); + --pill-input-text: white; + --pill-input-background: var(--accent-2); + --pill-input-disabled-text: white; + --pill-input-disabled-background: black; } From fe90172656be199acf8e36038f689207681df3f1 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Sun, 12 Jan 2025 10:39:50 -0700 Subject: [PATCH 013/246] RC-96 | Add Boolean inputs for the item forms --- .../handlebarHelpers/inputs/booleanInput.mjs | 32 +++++++++++++++++++ module/handlebarHelpers/inputs/formFields.mjs | 3 +- templates/Apps/AllItemSheetV1/style.css | 5 +++ templates/css/elements/input.css | 6 ++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 module/handlebarHelpers/inputs/booleanInput.mjs diff --git a/module/handlebarHelpers/inputs/booleanInput.mjs b/module/handlebarHelpers/inputs/booleanInput.mjs new file mode 100644 index 0000000..cda20a9 --- /dev/null +++ b/module/handlebarHelpers/inputs/booleanInput.mjs @@ -0,0 +1,32 @@ +import { localizer } from "../../utils/Localizer.mjs"; + +const { randomID } = foundry.utils; + +export function booleanInput(input, data) { + const label = localizer(input.label); + const id = `${data.meta.idp}-${randomID(10)}`; + + if (data.meta.limited) { + return `
+ ${label} +
+ ??? +
+
`; + }; + + return `
+ +
+ +
+
`; +}; diff --git a/module/handlebarHelpers/inputs/formFields.mjs b/module/handlebarHelpers/inputs/formFields.mjs index 9b70d55..79b2f29 100644 --- a/module/handlebarHelpers/inputs/formFields.mjs +++ b/module/handlebarHelpers/inputs/formFields.mjs @@ -1,4 +1,5 @@ import { barInput } from "./barInput.mjs"; +import { booleanInput } from "./booleanInput.mjs"; import { dropdownInput } from "./dropdownInput.mjs"; import { numberInput } from "./numberInput.mjs"; import { stringSet } from "./stringSet.mjs"; @@ -10,7 +11,7 @@ const inputTypes = { integer: numberInput, bar: barInput, dropdown: dropdownInput, - boolean: displayOnly, + boolean: booleanInput, }; const typesToSanitize = new Set([ `string`, `number` ]); diff --git a/templates/Apps/AllItemSheetV1/style.css b/templates/Apps/AllItemSheetV1/style.css index 247101c..9f95b26 100644 --- a/templates/Apps/AllItemSheetV1/style.css +++ b/templates/Apps/AllItemSheetV1/style.css @@ -61,4 +61,9 @@ [data-tag-count="0"] { justify-content: start; } + + [data-input-type="boolean"] > .checkbox-container { + display: flex; + justify-content: right; + } } diff --git a/templates/css/elements/input.css b/templates/css/elements/input.css index c800d7c..34604d4 100644 --- a/templates/css/elements/input.css +++ b/templates/css/elements/input.css @@ -16,6 +16,12 @@ border-bottom: var(--input-underline); } + &[type="checkbox"] { + all: revert-layer; + --checkbox-checked-color: var(--accent-3); + --checkbox-background-color: var(--accent-2); + } + &::placeholder { color: var(--input-placeholder-text); } From bd92e6928a7cab2ec5fae904c376bfc3b7dc1462 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Mon, 13 Jan 2025 23:21:58 -0700 Subject: [PATCH 014/246] RC-97 | Add Context Menu for embedded weapons --- assets/_credit.txt | 5 ++- assets/icons/edit.svg | 4 ++ assets/icons/roll.svg | 2 +- module/Apps/ActorSheets/HeroSummaryCardV1.mjs | 39 ++++++++++++++++++- templates/Apps/HeroSummaryCardV1/content.hbs | 19 ++++++++- templates/Apps/HeroSummaryCardV1/style.css | 7 +++- templates/css/elements/span.css | 7 ++++ 7 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 assets/icons/edit.svg diff --git a/assets/_credit.txt b/assets/_credit.txt index 19babdc..d2a13c1 100644 --- a/assets/_credit.txt +++ b/assets/_credit.txt @@ -1,2 +1,5 @@ Soetarman Atmodjo: - - icons/roll.svg : Rights Purchased. + - icons/roll.svg (https://thenounproject.com/icon/dice-5195278/) : Rights Purchased. + +SuperNdre: + - icons/edit.svg (https://thenounproject.com/icon/edit-5208207/) : Rights Purchased \ No newline at end of file diff --git a/assets/icons/edit.svg b/assets/icons/edit.svg new file mode 100644 index 0000000..acae8d6 --- /dev/null +++ b/assets/icons/edit.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/roll.svg b/assets/icons/roll.svg index 4d2a61b..51fb7ed 100644 --- a/assets/icons/roll.svg +++ b/assets/icons/roll.svg @@ -1,4 +1,4 @@ - + diff --git a/module/Apps/ActorSheets/HeroSummaryCardV1.mjs b/module/Apps/ActorSheets/HeroSummaryCardV1.mjs index c38b6f4..888ae4d 100644 --- a/module/Apps/ActorSheets/HeroSummaryCardV1.mjs +++ b/module/Apps/ActorSheets/HeroSummaryCardV1.mjs @@ -6,6 +6,7 @@ import { Logger } from "../../utils/Logger.mjs"; const { HandlebarsApplicationMixin } = foundry.applications.api; const { ActorSheetV2 } = foundry.applications.sheets; +const { ContextMenu } = foundry.applications.ui; export class HeroSummaryCardV1 extends GenericAppMixin(HandlebarsApplicationMixin(ActorSheetV2)) { @@ -22,7 +23,9 @@ export class HeroSummaryCardV1 extends GenericAppMixin(HandlebarsApplicationMixi window: { resizable: false, }, - actions: {}, + actions: { + editItem: (_event, target) => this._editItem(target), + }, form: { submitOnChange: true, closeOnSubmit: false, @@ -37,6 +40,32 @@ export class HeroSummaryCardV1 extends GenericAppMixin(HandlebarsApplicationMixi // #endregion // #region Lifecycle + async _onRender(context, options) { + await super._onRender(context, options); + + const itemMenuOptions = [ + { + name: `Edit`, + condition: () => this.isEditable, + callback: HeroSummaryCardV1._editItem, + }, + { + name: `Delete`, + condition: () => this.isEditable, + callback: async (el) => { + const itemEl = el.closest(`[data-item-id]`); + if (!itemEl) { return }; + const itemId = itemEl.dataset.itemId; + const item = await fromUuid(itemId); + await item.delete(); + }, + }, + ]; + if (itemMenuOptions.length) { + new ContextMenu(this.element, `.weapon-ctx-menu`, itemMenuOptions, { jQuery: false, fixed: true }); + } + }; + async _preparePartContext(partId, ctx, opts) { ctx = await super._preparePartContext(partId, ctx, opts); ctx.actor = this.document; @@ -135,5 +164,13 @@ export class HeroSummaryCardV1 extends GenericAppMixin(HandlebarsApplicationMixi // #endregion // #region Actions + static async _editItem(target) { + const itemEl = target.closest(`[data-item-id]`); + if (!itemEl) { return }; + const itemId = itemEl.dataset.itemId; + if (!itemId) { return }; + const item = await fromUuid(itemId); + item.sheet.render({ force: true }); + }; // #endregion }; diff --git a/templates/Apps/HeroSummaryCardV1/content.hbs b/templates/Apps/HeroSummaryCardV1/content.hbs index 0c6c508..36414fb 100644 --- a/templates/Apps/HeroSummaryCardV1/content.hbs +++ b/templates/Apps/HeroSummaryCardV1/content.hbs @@ -181,8 +181,23 @@ {{else}} -
- {{ slot.data.name }} +
+ + +
+ {{ slot.data.name }} + + {{#if slot.data.system.traitString}} {{ slot.data.system.traitString }} diff --git a/templates/Apps/HeroSummaryCardV1/style.css b/templates/Apps/HeroSummaryCardV1/style.css index 1f8ef4f..57cabbe 100644 --- a/templates/Apps/HeroSummaryCardV1/style.css +++ b/templates/Apps/HeroSummaryCardV1/style.css @@ -91,13 +91,18 @@ display: grid; grid-template-columns: subgrid; grid-template-rows: subgrid; - overflow-y: auto; thead, tbody, tr { display: contents; } + td { + display: flex; + flex-direction: row; + align-items: center; + gap: 4px; + } .row-alt > * { background: inherit; } diff --git a/templates/css/elements/span.css b/templates/css/elements/span.css index 65a1858..25c1ca9 100644 --- a/templates/css/elements/span.css +++ b/templates/css/elements/span.css @@ -3,6 +3,13 @@ font-size: var(--font-size-10) } + &.ellipses { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } + + /* Makes it so that spans are never less than the font size */ &:empty::before { content: "\200b"; } From 39ab64be49aff2dcfb881c34fa0043440b1b7619 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Mon, 13 Jan 2025 23:22:09 -0700 Subject: [PATCH 015/246] Add fromUuid as a global method --- eslint.config.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/eslint.config.mjs b/eslint.config.mjs index 5cbe12c..6fab321 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -30,6 +30,7 @@ export default [ Dialog: `readonly`, renderTemplate: `readonly`, TextEditor: `readonly`, + fromUuid: `readonly`, }, }, }, From 6aa89b21736b03998f503583e1eb050191ebc4d6 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Mon, 13 Jan 2025 23:28:34 -0700 Subject: [PATCH 016/246] RC-100 | Armour | Setup Data Model --- langs/en-ca.json | 1 + module/data/Item/Armour.mjs | 25 +++++++++++++++++++++++++ module/hooks/init.mjs | 4 ++++ system.json | 1 + 4 files changed, 31 insertions(+) create mode 100644 module/data/Item/Armour.mjs diff --git a/langs/en-ca.json b/langs/en-ca.json index c496c58..c27af21 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -4,6 +4,7 @@ "hero": "Hero" }, "Item": { + "armour": "Armour", "weapon": "Weapon" } }, diff --git a/module/data/Item/Armour.mjs b/module/data/Item/Armour.mjs new file mode 100644 index 0000000..dbb1ea6 --- /dev/null +++ b/module/data/Item/Armour.mjs @@ -0,0 +1,25 @@ +const { fields } = foundry.data; + +export class ArmourData extends foundry.abstract.TypeDataModel { + // MARK: Schema + static defineSchema() { + return {}; + }; + + // MARK: Base Data + prepareBaseData() { + super.prepareBaseData(); + }; + + // MARK: Derived Data + prepareDerivedData() { + super.prepareDerivedData(); + }; + + // #region Sheet Data + getFormFields(ctx) { + const fields = []; + return fields; + }; + // #endregion +}; diff --git a/module/hooks/init.mjs b/module/hooks/init.mjs index e76673f..9abc757 100644 --- a/module/hooks/init.mjs +++ b/module/hooks/init.mjs @@ -4,6 +4,7 @@ import { HeroSkillsCardV1 } from "../Apps/ActorSheets/HeroSkillsCardV1.mjs"; import { HeroSummaryCardV1 } from "../Apps/ActorSheets/HeroSummaryCardV1.mjs"; // Data Models +import { ArmourData } from "../data/Item/Armour.mjs"; import { HeroData } from "../data/Actor/Hero.mjs"; import { WeaponData } from "../data/Item/Weapon.mjs"; @@ -15,18 +16,21 @@ import helpers from "../handlebarHelpers/_index.mjs"; import { Logger } from "../utils/Logger.mjs"; import { registerCustomComponents } from "../Apps/elements/_index.mjs"; import { registerDevSettings } from "../settings/devSettings.mjs"; +import { registerMetaSettings } from "../settings/metaSettings.mjs"; import { registerUserSettings } from "../settings/userSettings.mjs"; Hooks.once(`init`, () => { Logger.log(`Initializing`); // #region Settings + registerMetaSettings(); registerDevSettings(); registerUserSettings(); // #endregion // #region Datamodels CONFIG.Actor.dataModels.hero = HeroData; + CONFIG.Item.dataModels.armour = ArmourData; CONFIG.Item.dataModels.weapon = WeaponData; // #endregion diff --git a/system.json b/system.json index d6f4e28..526138b 100644 --- a/system.json +++ b/system.json @@ -44,6 +44,7 @@ "hero": {} }, "Item": { + "armour": {}, "weapon": {} } } From 4948c7e755e50588a7cc74484d9abdb5b09f4d17 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Wed, 15 Jan 2025 19:51:31 -0700 Subject: [PATCH 017/246] RC-102 | Armour | Protection --- langs/en-ca.json | 3 ++- module/data/Item/Armour.mjs | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/langs/en-ca.json b/langs/en-ca.json index c27af21..5aaeccd 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -62,7 +62,8 @@ "Uncommon": "Uncommon", "Rare": "Rare", "Scarce": "Scarce" - } + }, + "protection": "Protection" }, "setting": { "abbrAccess": { diff --git a/module/data/Item/Armour.mjs b/module/data/Item/Armour.mjs index dbb1ea6..fe80576 100644 --- a/module/data/Item/Armour.mjs +++ b/module/data/Item/Armour.mjs @@ -1,9 +1,13 @@ +import { requiredInteger } from "../helpers.mjs"; + const { fields } = foundry.data; export class ArmourData extends foundry.abstract.TypeDataModel { // MARK: Schema static defineSchema() { - return {}; + return { + protection: requiredInteger({ min: 0, initial: 1 }), + }; }; // MARK: Base Data @@ -18,7 +22,15 @@ export class ArmourData extends foundry.abstract.TypeDataModel { // #region Sheet Data getFormFields(ctx) { - const fields = []; + const fields = [ + { + type: `integer`, + label: `RipCrypt.common.protection`, + value: this.protection, + path: `system.protection`, + min: 0, + }, + ]; return fields; }; // #endregion From 3ffbc57546f4e8da5bf38ee68252255898bccca8 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Wed, 15 Jan 2025 20:16:32 -0700 Subject: [PATCH 018/246] RC-101 | Armour | Add Location Data --- langs/en-ca.json | 6 ++++-- module/data/Item/Armour.mjs | 26 ++++++++++++++++++++++++++ module/gameTerms.mjs | 8 +++++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/langs/en-ca.json b/langs/en-ca.json index 5aaeccd..66c2ae8 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -63,7 +63,8 @@ "Rare": "Rare", "Scarce": "Scarce" }, - "protection": "Protection" + "protection": "Protection", + "location": "Location" }, "setting": { "abbrAccess": { @@ -87,7 +88,8 @@ "short-range": "Short @RipCrypt.common.range", "long-range": "Long @RipCrypt.common.range", "current-wear": "Current @RipCrypt.common.wear", - "max-wear": "Maximum @RipCrypt.common.wear" + "max-wear": "Maximum @RipCrypt.common.wear", + "location-placeholder": "New Location..." } } } diff --git a/module/data/Item/Armour.mjs b/module/data/Item/Armour.mjs index fe80576..2bcc23c 100644 --- a/module/data/Item/Armour.mjs +++ b/module/data/Item/Armour.mjs @@ -1,3 +1,4 @@ +import { gameTerms } from "../../gameTerms.mjs"; import { requiredInteger } from "../helpers.mjs"; const { fields } = foundry.data; @@ -7,6 +8,18 @@ export class ArmourData extends foundry.abstract.TypeDataModel { static defineSchema() { return { protection: requiredInteger({ min: 0, initial: 1 }), + location: new fields.SetField( + new fields.StringField({ + blank: false, + trim: true, + nullable: false, + options: Object.values(gameTerms.Anatomy), + }), + { + nullable: false, + required: true, + }, + ), }; }; @@ -20,9 +33,22 @@ export class ArmourData extends foundry.abstract.TypeDataModel { super.prepareDerivedData(); }; + // #region Getters + get locationString() { + return [...this.location].join(`, `); + }; + // #endregion + // #region Sheet Data getFormFields(ctx) { const fields = [ + { + type: `string-set`, + label: `RipCrypt.common.location`, + placeholder: `RipCrypt.Apps.location-placeholder`, + path: `system.location`, + value: this.locationString, + }, { type: `integer`, label: `RipCrypt.common.protection`, diff --git a/module/gameTerms.mjs b/module/gameTerms.mjs index b1a1130..e65ca26 100644 --- a/module/gameTerms.mjs +++ b/module/gameTerms.mjs @@ -15,6 +15,12 @@ export const gameTerms = Object.preventExtensions({ NOVICE: `Novice`, ADEPT: `Adept`, EXPERT: `Expert`, - Master: `Master`, + MASTER: `Master`, }, + Anatomy: Object.freeze({ + HEAD: `head`, + BODY: `body`, + ARMS: `arms`, + LEGS: `legs`, + }), }); From c1f0e8d9c53fbfcb42cde0e889d335ca895b6f9a Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Wed, 15 Jan 2025 20:16:44 -0700 Subject: [PATCH 019/246] Add missing semicolons --- module/data/Item/Weapon.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/data/Item/Weapon.mjs b/module/data/Item/Weapon.mjs index a2ec6b7..35a7f89 100644 --- a/module/data/Item/Weapon.mjs +++ b/module/data/Item/Weapon.mjs @@ -46,14 +46,14 @@ export class WeaponData extends foundry.abstract.TypeDataModel { // #region Getters get traitString() { return [...this.traits].join(`, `); - } + }; get rangeString() { if (this.range.short && this.range.long) { return `${this.range.short} / ${this.range.long}`; }; return String(this.range.short ?? this.range.long ?? ``); - } + }; // #endregion // #region Sheet Data From 07f3b2489743783cd13e228b4f8b2bbfd49d7ea3 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Wed, 15 Jan 2025 21:02:17 -0700 Subject: [PATCH 020/246] RC-105 | Add an rc-svg component for ease of SVG-loading, and add the hero silhouette to the sheet --- assets/_credit.txt | 3 +++ assets/hero-silhouette.svg | 3 +++ module/Apps/elements/Icon.mjs | 2 +- module/Apps/elements/_index.mjs | 2 ++ .../elements/mixins/StyledShadowElement.mjs | 2 +- module/Apps/elements/svgLoader.mjs | 11 ++++++++++ templates/Apps/HeroSummaryCardV1/content.hbs | 8 +++++++ templates/Apps/HeroSummaryCardV1/style.css | 14 ++++++++++-- templates/css/components/svg-loader.css | 22 +++++++++++++++++++ 9 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 assets/hero-silhouette.svg create mode 100644 module/Apps/elements/svgLoader.mjs create mode 100644 templates/css/components/svg-loader.css diff --git a/assets/_credit.txt b/assets/_credit.txt index d2a13c1..b58b8a5 100644 --- a/assets/_credit.txt +++ b/assets/_credit.txt @@ -1,3 +1,6 @@ +Kýnan Antos (Gritsilk Games): + - hero-silhouette.svg : Licensed to Distribute and Modify within the bounds of the "Foundry-RipCrypt" system. + Soetarman Atmodjo: - icons/roll.svg (https://thenounproject.com/icon/dice-5195278/) : Rights Purchased. diff --git a/assets/hero-silhouette.svg b/assets/hero-silhouette.svg new file mode 100644 index 0000000..12e2bb5 --- /dev/null +++ b/assets/hero-silhouette.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/module/Apps/elements/Icon.mjs b/module/Apps/elements/Icon.mjs index 722ee36..4738c23 100644 --- a/module/Apps/elements/Icon.mjs +++ b/module/Apps/elements/Icon.mjs @@ -123,4 +123,4 @@ export class RipCryptIcon extends StyledShadowElement(HTMLElement) { temp.innerHTML = content; return temp.querySelector(`svg`); }; -}; \ No newline at end of file +}; diff --git a/module/Apps/elements/_index.mjs b/module/Apps/elements/_index.mjs index baaef94..4bde4f2 100644 --- a/module/Apps/elements/_index.mjs +++ b/module/Apps/elements/_index.mjs @@ -1,8 +1,10 @@ import { Logger } from "../../utils/Logger.mjs"; import { RipCryptIcon } from "./Icon.mjs"; +import { RipCryptSVGLoader } from "./svgLoader.mjs"; const components = [ RipCryptIcon, + RipCryptSVGLoader, ]; export function registerCustomComponents() { diff --git a/module/Apps/elements/mixins/StyledShadowElement.mjs b/module/Apps/elements/mixins/StyledShadowElement.mjs index c645111..5eb6894 100644 --- a/module/Apps/elements/mixins/StyledShadowElement.mjs +++ b/module/Apps/elements/mixins/StyledShadowElement.mjs @@ -69,4 +69,4 @@ export function StyledShadowElement(Base) { } }; }; -}; \ No newline at end of file +}; diff --git a/module/Apps/elements/svgLoader.mjs b/module/Apps/elements/svgLoader.mjs new file mode 100644 index 0000000..d9bf622 --- /dev/null +++ b/module/Apps/elements/svgLoader.mjs @@ -0,0 +1,11 @@ +import { RipCryptIcon } from "./Icon.mjs"; + +/** +Attributes: +@property {string} name - The name of the icon, takes precedence over the path +@property {string} path - The path of the icon file +*/ +export class RipCryptSVGLoader extends RipCryptIcon { + static elementName = `rc-svg`; + static _stylePath = `css/components/svg-loader.css`; +}; diff --git a/templates/Apps/HeroSummaryCardV1/content.hbs b/templates/Apps/HeroSummaryCardV1/content.hbs index 36414fb..66058a4 100644 --- a/templates/Apps/HeroSummaryCardV1/content.hbs +++ b/templates/Apps/HeroSummaryCardV1/content.hbs @@ -23,6 +23,14 @@ {{ rc-i18n "RipCrypt.common.armour" }}
+
0
{{ rc-i18n "RipCrypt.common.anatomy.head" }} diff --git a/templates/Apps/HeroSummaryCardV1/style.css b/templates/Apps/HeroSummaryCardV1/style.css index 57cabbe..a08d0d4 100644 --- a/templates/Apps/HeroSummaryCardV1/style.css +++ b/templates/Apps/HeroSummaryCardV1/style.css @@ -145,6 +145,7 @@ border-radius: 50%; font-size: 1.5rem; position: relative; + background: var(--base-background); > .value { background: none; @@ -162,8 +163,8 @@ } &.small { - --size: 30px; - font-size: 1.15rem; + --size: 35px; + font-size: 1.1rem; } &.dual { @@ -216,12 +217,21 @@ grid-template-rows: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.2fr); justify-items: center; align-items: center; + position: relative; > div { display: flex; flex-direction: column; justify-content: center; align-items: center; + z-index: 1; + } + + > rc-svg { + position: absolute; + bottom: 0; + left: 0; + width: 58%; } } diff --git a/templates/css/components/svg-loader.css b/templates/css/components/svg-loader.css new file mode 100644 index 0000000..b843bc5 --- /dev/null +++ b/templates/css/components/svg-loader.css @@ -0,0 +1,22 @@ +:host { + display: inline-block; +} + +div { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; +} + +svg { + fill: var(--fill); + stroke: var(--stroke); +} + +path { + stroke: var(--stroke); + stroke-width: var(--stroke-width); + stroke-linejoin: var(--stroke-linejoin); +} From d1ce14411476467e72af104e6fc5514142206dc8 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Fri, 17 Jan 2025 19:24:53 -0700 Subject: [PATCH 021/246] RC-106 | Add equipped armour display --- module/Apps/ActorSheets/HeroSummaryCardV1.mjs | 15 +++++++++ module/data/Actor/Hero.mjs | 33 +++++++++++++++++++ module/data/Item/Armour.mjs | 5 +++ templates/Apps/HeroSummaryCardV1/content.hbs | 4 +++ templates/Apps/HeroSummaryCardV1/style.css | 10 ++++++ 5 files changed, 67 insertions(+) diff --git a/module/Apps/ActorSheets/HeroSummaryCardV1.mjs b/module/Apps/ActorSheets/HeroSummaryCardV1.mjs index 888ae4d..434846e 100644 --- a/module/Apps/ActorSheets/HeroSummaryCardV1.mjs +++ b/module/Apps/ActorSheets/HeroSummaryCardV1.mjs @@ -72,6 +72,7 @@ export class HeroSummaryCardV1 extends GenericAppMixin(HandlebarsApplicationMixi ctx = await HeroSummaryCardV1.prepareGuts(ctx); ctx = await HeroSummaryCardV1.prepareWeapons(ctx); + ctx = await HeroSummaryCardV1.prepareArmor(ctx); ctx = await HeroSummaryCardV1.prepareFatePath(ctx); ctx = await HeroSummaryCardV1.prepareAbilityRow(ctx); ctx = await HeroSummaryCardV1.prepareSpeed(ctx); @@ -136,6 +137,20 @@ export class HeroSummaryCardV1 extends GenericAppMixin(HandlebarsApplicationMixi return ctx; }; + static async prepareArmor(ctx) { + ctx.armours = {}; + const equipped = ctx.actor.system.equippedArmour; + for (const slot of gameTerms.Anatomy) { + const item = equipped[slot]; + ctx.armours[slot] = { + name: item?.name ?? ``, + uuid: item?.uuid ?? ``, + defense: 0, + }; + }; + return ctx; + }; + static async prepareWeapons(ctx) { const limit = ctx.actor.system.limit.weapons; const embedded = ctx.actor.itemTypes.weapon; diff --git a/module/data/Actor/Hero.mjs b/module/data/Actor/Hero.mjs index b38d26b..0521699 100644 --- a/module/data/Actor/Hero.mjs +++ b/module/data/Actor/Hero.mjs @@ -147,4 +147,37 @@ export class HeroData extends foundry.abstract.TypeDataModel { run: (this.ability.gait + 3) * 2, }; }; + + // #region Getters + get equippedArmour() { + const armours = this.parent.itemTypes.armour; + const slots = Object.fromEntries( + gameTerms.Anatomy.map(v => [v, null]), + ); + for (const armour of armours) { + if (!armour.system.equipped) { continue }; + for (const locationTag of [...armour.system.location.values()]) { + const location = locationTag.toLowerCase(); + slots[location] = armour; + }; + }; + return slots; + }; + + get equippedShield() { + return null; + }; + + get defense() { + const defenses = {}; + const armour = this.equippedArmour; + for (const slot in armour) { + defenses[slot] = armour[slot]?.system.protection ?? 0; + }; + + // TODO: add shield defenses + + return defenses; + }; + // #endregion }; diff --git a/module/data/Item/Armour.mjs b/module/data/Item/Armour.mjs index 2bcc23c..b12e969 100644 --- a/module/data/Item/Armour.mjs +++ b/module/data/Item/Armour.mjs @@ -20,6 +20,11 @@ export class ArmourData extends foundry.abstract.TypeDataModel { required: true, }, ), + equipped: new fields.BooleanField({ + initial: false, + required: true, + nullable: false, + }), }; }; diff --git a/templates/Apps/HeroSummaryCardV1/content.hbs b/templates/Apps/HeroSummaryCardV1/content.hbs index 66058a4..2c0ab0b 100644 --- a/templates/Apps/HeroSummaryCardV1/content.hbs +++ b/templates/Apps/HeroSummaryCardV1/content.hbs @@ -54,15 +54,19 @@