diff --git a/.env.template b/.env.template new file mode 100644 index 0000000..180dbd6 --- /dev/null +++ b/.env.template @@ -0,0 +1,2 @@ +# The absolute path to the Foundry installation to create symlinks to +FOUNDRY_ROOT="" diff --git a/.github/workflows/draft-release.yaml b/.github/workflows/draft-release.yaml index aba5033..eecafc4 100644 --- a/.github/workflows/draft-release.yaml +++ b/.github/workflows/draft-release.yaml @@ -29,16 +29,22 @@ jobs: if: ${{ steps.check-tag.outputs.exists == 'true' }} run: exit 1 - - name: Move system.json to a temp file - id: manifest-move - run: mv system.json module.temp.json + - name: "Building compendia" + run: "npm run data:build" - - name: Update the download property in the manifest + - name: "Removing compendium source" + run: "rm -rf packs/**/_source" + + - name: Update the manifest with the relevant properties id: manifest-update - run: cat module.temp.json | jq -r --tab '.download = "https://github.com/${{ github.repository }}/releases/download/v${{ steps.version.outputs.version }}/release.zip"' > system.json + uses: microsoft/variable-substitution@v1 + with: + files: "system.json" + env: + download: "https://github.com/${{ github.repository }}/releases/download/v${{ steps.version.outputs.version }}/release.zip" - name: Create the zip - run: zip -r release.zip system.json module langs assets templates README.md + run: zip -r release.zip system.json packs module langs assets templates README.md - name: Create the draft release uses: ncipollo/release-action@v1 diff --git a/.gitignore b/.gitignore index a86caf7..e058206 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ dist/ *.link *.txt +/foundry # Dependency directories node_modules/ @@ -12,3 +13,10 @@ jspm_packages/ .env.test.local .env.production.local .env.local + +# Ignore all of the binaries and stuff that gets built for Foundry from the raw +# JSON data because it's annoying seeing it in my git changes when it isn't actually +# needed. +/packs/**/* +!/packs/**/*/ +!/packs/**/*.json diff --git a/.vscode/settings.json b/.vscode/settings.json index 8463326..c60389c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,10 @@ { "files.exclude": { - "**/node_modules": true + "**/node_modules": true, + "foundry": true }, "search.exclude": { - "foundry.*.link": true + "foundry": true }, "html.customData": [ "./.vscode/foundry.html-data.json", diff --git a/assets/_credit.txt b/assets/_credit.txt index bac6dc2..83c76aa 100644 --- a/assets/_credit.txt +++ b/assets/_credit.txt @@ -1,8 +1,11 @@ -Oliver Akins: +Eldritch-Oliver: - geist-silhouette.v2.svg : All rights reserved. - caster-silhouette.v1.svg : All rights reserved. - icons/star-empty.svg : Modified from https://thenounproject.com/icon/star-7711815/ by Llisole - icons/star.svg : Modified from https://thenounproject.com/icon/star-7711815/ by Llisole + - icons/shield/checked.v1.svg : Modified from https://thenounproject.com/icon/shield-5565751/ by Corner Pixel + - icons/shield/crossed.v1.svg : Modified from https://thenounproject.com/icon/shield-5565751/ by Corner Pixel + - icons/shield/solid.v1.svg : Modified from https://thenounproject.com/icon/shield-5565751/ by Corner Pixel Kýnan Antos (Gritsilk Games): - hero-silhouette.svg : Licensed to Distribute and Modify within the bounds of the "Foundry-RipCrypt" system. @@ -13,6 +16,9 @@ ARISO: Abdulloh Fauzan: - icons/info-circle.svg (https://thenounproject.com/icon/information-4176576/) : Rights Purchased +hanifmuhammad: + - icons/plus.svg (https://thenounproject.com/icon/plus-7363257/) : Rights Purchased + QOLBIN SALIIM: - icons/arrow-left.svg (https://thenounproject.com/icon/arrow-1933583/) : Rights Purchased - icons/arrow-right.svg (https://thenounproject.com/icon/arrow-1933581/) : Rights Purchased diff --git a/assets/icons/plus.svg b/assets/icons/plus.svg new file mode 100644 index 0000000..5e8c131 --- /dev/null +++ b/assets/icons/plus.svg @@ -0,0 +1,3 @@ + diff --git a/assets/icons/shield/checked.v1.svg b/assets/icons/shield/checked.v1.svg new file mode 100644 index 0000000..c22ff10 --- /dev/null +++ b/assets/icons/shield/checked.v1.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/shield/crossed.v1.svg b/assets/icons/shield/crossed.v1.svg new file mode 100644 index 0000000..bfcae76 --- /dev/null +++ b/assets/icons/shield/crossed.v1.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/shield/solid.v1.svg b/assets/icons/shield/solid.v1.svg new file mode 100644 index 0000000..7f37ece --- /dev/null +++ b/assets/icons/shield/solid.v1.svg @@ -0,0 +1 @@ + diff --git a/augments.d.ts b/augments.d.ts new file mode 100644 index 0000000..dc091c2 --- /dev/null +++ b/augments.d.ts @@ -0,0 +1,14 @@ +declare global { + class Hooks extends foundry.helpers.Hooks {}; + const fromUuid = foundry.utils.fromUuid; +} + +interface Actor { + /** The system-specific data */ + system: any; +}; + +interface Item { + /** The system-specific data */ + system: any; +}; \ No newline at end of file diff --git a/eslint.config.mjs b/eslint.config.mjs index a0d500d..4ef4c09 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -4,7 +4,7 @@ import stylistic from "@stylistic/eslint-plugin"; export default [ // Tell eslint to ignore files that I don't mind being formatted slightly differently - { ignores: [ `scripts/` ] }, + { ignores: [ `scripts/`, `foundry/` ] }, { languageOptions: { globals: globals.browser, @@ -75,7 +75,7 @@ export default [ "@stylistic/eol-last": `warn`, "@stylistic/operator-linebreak": [`warn`, `before`], "@stylistic/indent": [`warn`, `tab`], - "@stylistic/brace-style": [`warn`, `1tbs`, { "allowSingleLine": true }], + "@stylistic/brace-style": [`warn`, `stroustrup`, { "allowSingleLine": true }], "@stylistic/quotes": [`warn`, `backtick`, { "avoidEscape": true }], "@stylistic/comma-dangle": [`warn`, { arrays: `always-multiline`, objects: `always-multiline`, imports: `always-multiline`, exports: `always-multiline`, functions: `always-multiline` }], "@stylistic/comma-style": [`warn`, `last`], diff --git a/jsconfig.json b/jsconfig.json index 8b0d1fc..47b5b55 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,11 +1,19 @@ { "compilerOptions": { - "module": "ES2020", - "target": "ES2020" + "module": "es2022", + "target": "es2022", + "types": [ + "./augments.d.ts" + ], + "paths": { + "@client/*": ["./foundry/client/*"], + "@common/*": ["./foundry/common/*"], + } }, - "exclude": ["node_modules", "**/node_modules/*"], - "include": ["module/**/*", "foundry.v13.link/client/**/*.js", "foundry.v13.link/**/*.mjs"], - "typeAcquisition": { - "include": ["jquery"] - } + "include": [ + "module/**/*", + "foundry/client/client.mjs", + "foundry/client/global.d.mts", + "foundry/common/primitives/global.d.mts" + ] } \ No newline at end of file diff --git a/langs/en-ca.json b/langs/en-ca.json index d606190..a5d28cc 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -17,6 +17,7 @@ "RipCrypt": { "sheet-names": { "AllItemsSheetV1": "RipCrypt Item Sheet", + "ArmourSheet": "Armour Sheet", "CombinedHeroSheet": "Hero Sheet", "StatsCardV1": "Hero Stat Card", "CraftCardV1": "Hero Craft Card", @@ -154,9 +155,14 @@ "both": "Notification and Pause Game", "nothing": "Do Nothing" } + }, + "allowUpdateSandsSocket": { + "name": "Player Haste Updates the Sands of Fate", + "hint": "This setting determines if when a player makes a haste check that the result will automatically be applied to the global Sands of Fate. Disabling this is good if you want to let players roll without needing to worry about automation messing anything up while they spam rolls." } }, "Apps": { + "damage-reduction": "@RipCrypt.common.damage reduction", "traits-range": "@RipCrypt.common.traits & @RipCrypt.common.range", "grit-skills": "@RipCrypt.common.abilities.grit Skills", "gait-skills": "@RipCrypt.common.abilities.gait Skills", @@ -184,13 +190,18 @@ "star-button-tooltip": "Add Star", "unstar-button": "Remove {name} as a starred ammo", "unstar-button-tooltip": "Remove Star" - } + }, + "protects-the-location": "Protects your {part}" }, "notifs": { "error": { "cannot-equip": "Cannot equip the {itemType}, see console for more details.", "invalid-delta": "The delta for \"{name}\" is not a number, cannot finish processing the action.", - "at-favourite-limit": "Cannot favourite more than three items, unfavourite one to make space." + "at-favourite-limit": "Cannot favourite more than three items, unfavourite one to make space.", + "invalid-socket": "Invalid socket data received, this means a module or system bug is present.", + "unknown-socket-event": "An unknown socket event was received: {event}", + "no-active-gm": "No active @USER.GM is logged in, you must wait for a @USER.GM to be active before you can do that.", + "malformed-socket-payload": "Socket event \"{event}\" received with malformed payload. Details: {details}" }, "warn": { "cannot-go-negative": "\"{name}\" is unable to be a negative number." @@ -203,6 +214,7 @@ "shield-bonus": "Shield Bonus: {value}", "set-fate-to": "Set Fate to {ordinal}", "current-tour": "Current Delve Tour", + "create-new-item": "Create new item", "next-tour": "Next Delve Tour", "prev-tour": "Previous Delve Tour", "auras": { diff --git a/module/Apps/ActorSheets/CombinedHeroSheet.mjs b/module/Apps/ActorSheets/CombinedHeroSheet.mjs index 75bde71..b81923a 100644 --- a/module/Apps/ActorSheets/CombinedHeroSheet.mjs +++ b/module/Apps/ActorSheets/CombinedHeroSheet.mjs @@ -1,7 +1,6 @@ import { CraftCardV1 } from "./CraftCardV1.mjs"; import { filePath } from "../../consts.mjs"; import { GenericAppMixin } from "../GenericApp.mjs"; -import { Logger } from "../../utils/Logger.mjs"; import { SkillsCardV1 } from "./SkillsCardV1.mjs"; import { StatsCardV1 } from "./StatsCardV1.mjs"; @@ -23,7 +22,9 @@ export class CombinedHeroSheet extends GenericAppMixin(HandlebarsApplicationMixi window: { resizable: false, }, - actions: {}, + actions: { + ...StatsCardV1.DEFAULT_OPTIONS.actions, + }, form: { submitOnChange: true, closeOnSubmit: false, @@ -106,7 +107,6 @@ export class CombinedHeroSheet extends GenericAppMixin(HandlebarsApplicationMixi }; }; - Logger.debug(`Context keys:`, Object.keys(ctx)); return ctx; }; // #endregion diff --git a/module/Apps/ActorSheets/CraftCardV1.mjs b/module/Apps/ActorSheets/CraftCardV1.mjs index 808843d..4a650df 100644 --- a/module/Apps/ActorSheets/CraftCardV1.mjs +++ b/module/Apps/ActorSheets/CraftCardV1.mjs @@ -115,7 +115,8 @@ export class CraftCardV1 extends GenericAppMixin(HandlebarsApplicationMixin(Acto const length = crafts.length; if (length >= limit) { crafts = crafts.slice(0, limit); - } else { + } + else { crafts = crafts .concat(Array(limit - length).fill(null)) .slice(0, limit); diff --git a/module/Apps/ActorSheets/SkillsCardV1.mjs b/module/Apps/ActorSheets/SkillsCardV1.mjs index 9be3429..b0231f3 100644 --- a/module/Apps/ActorSheets/SkillsCardV1.mjs +++ b/module/Apps/ActorSheets/SkillsCardV1.mjs @@ -194,7 +194,8 @@ export class SkillsCardV1 extends GenericAppMixin(HandlebarsApplicationMixin(Act const length = ctx.skills[ability].length; if (length >= limit) { ctx.skills[ability] = ctx.skills[ability].slice(0, limit); - } else { + } + else { ctx.skills[ability] = ctx.skills[ability] .concat(Array(limit - length).fill(null)) .slice(0, limit); diff --git a/module/Apps/ActorSheets/StatsCardV1.mjs b/module/Apps/ActorSheets/StatsCardV1.mjs index 155168e..cd44ead 100644 --- a/module/Apps/ActorSheets/StatsCardV1.mjs +++ b/module/Apps/ActorSheets/StatsCardV1.mjs @@ -1,4 +1,5 @@ import { deleteItemFromElement, editItemFromElement } from "../utils.mjs"; +import { DelveDiceHUD } from "../DelveDiceHUD.mjs"; import { filePath } from "../../consts.mjs"; import { gameTerms } from "../../gameTerms.mjs"; import { GenericAppMixin } from "../GenericApp.mjs"; @@ -25,6 +26,7 @@ export class StatsCardV1 extends GenericAppMixin(HandlebarsApplicationMixin(Acto resizable: false, }, actions: { + rollForHaste: DelveDiceHUD.rollForHaste, }, form: { submitOnChange: true, diff --git a/module/Apps/DelveDiceHUD.mjs b/module/Apps/DelveDiceHUD.mjs index dfa14a5..9599fa1 100644 --- a/module/Apps/DelveDiceHUD.mjs +++ b/module/Apps/DelveDiceHUD.mjs @@ -6,6 +6,7 @@ import { Logger } from "../utils/Logger.mjs"; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; const { ContextMenu } = foundry.applications.ux; +const { Roll } = foundry.dice; const { FatePath } = gameTerms; const CompassRotations = { @@ -87,7 +88,8 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) { const existing = document.getElementById(element.id); if (existing) { existing.replaceWith(element); - } else { + } + else { const parent = document.getElementById(`ui-top`); parent.prepend(element); }; @@ -189,18 +191,7 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) { /** @this {DelveDiceHUD} */ static async #tourDelta(_event, element) { const delta = parseInt(element.dataset.delta); - const initial = game.settings.get(`ripcrypt`, `sandsOfFateInitial`); - let newSands = this._sandsOfFate + delta; - - if (newSands > initial) { - Logger.info(`Cannot go to a previous Delve Tour above the initial value`); - return; - }; - - if (newSands === 0) { - newSands = initial; - await this.alertCrypticEvent(); - }; + await this.sandsOfFateDelta(delta); switch (Math.sign(delta)) { case -1: { @@ -212,9 +203,6 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) { break; } }; - - this.#animateSandsTo(newSands); - game.settings.set(`ripcrypt`, `sandsOfFate`, newSands); }; /** @this {DelveDiceHUD} */ @@ -241,11 +229,77 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) { localizer(`RipCrypt.notifs.info.cryptic-event-alert`), { console: false }, ); + game.socket.emit(`system.ripcrypt`, { + event: `notify`, + payload: { + message: `RipCrypt.notifs.info.cryptic-event-alert`, + type: `info`, + }, + }); }; if ([`both`, `pause`].includes(alertType) && game.user.isGM) { game.togglePause(true, { broadcast: true }); }; }; + + /** + * Changes the current Sands of Fate by an amount provided, animating the + * @param {number} delta The amount of change + */ + async sandsOfFateDelta(delta) { + const initial = game.settings.get(`ripcrypt`, `sandsOfFateInitial`); + let newSands = this._sandsOfFate + delta; + + if (newSands > initial) { + Logger.info(`Cannot increase the Sands of Fate to a value about the initial`); + return; + }; + + if (newSands === 0) { + newSands = initial; + await this.alertCrypticEvent(); + }; + + this.#animateSandsTo(newSands); + game.settings.set(`ripcrypt`, `sandsOfFate`, newSands); + }; + + /** + * A helper method that rolls the dice required for hasty turns while delving + * and adjusts the Sands of Fate accordingly + */ + static async rollForHaste() { + const shouldUpdateSands = game.settings.get(`ripcrypt`, `allowUpdateSandsSocket`); + if (shouldUpdateSands && game.users.activeGM == null) { + ui.notifications.error(localizer(`RipCrypt.notifs.error.no-active-gm`)); + return; + }; + + const roll = new Roll(`1d8xo=1`); + await roll.evaluate(); + + let delta = 0; + if (roll.dice[0].results[0].exploded) { + delta = -1; + if (roll.dice[0].results[1].result === 1) { + delta = -2; + }; + }; + + roll.toMessage({ flavor: `Haste Check` }); + + // Change the Sands of Fate setting if required + if (delta === 0 || !shouldUpdateSands) { return }; + if (game.user.isActiveGM) { + ui.delveDice.sandsOfFateDelta(delta); + } + else { + game.socket.emit(`system.ripcrypt`, { + event: `updateSands`, + payload: { delta }, + }); + }; + }; // #endregion }; diff --git a/module/Apps/GenericApp.mjs b/module/Apps/GenericApp.mjs index 1fe5edf..0be30e4 100644 --- a/module/Apps/GenericApp.mjs +++ b/module/Apps/GenericApp.mjs @@ -4,7 +4,8 @@ import { RichEditor } from "./RichEditor.mjs"; import { toBoolean } from "../consts.mjs"; /** - * A mixin that takes the class from HandlebarsApplicationMixin and + * A mixin that takes the class from HandlebarsApplicationMixin and combines it + * with utility functions / data that is used across all RipCrypt applications */ export function GenericAppMixin(HandlebarsApp) { class GenericRipCryptApp extends HandlebarsApp { @@ -91,8 +92,9 @@ export function GenericAppMixin(HandlebarsApp) { ctx.meta.idp = this.document?.uuid ?? this.id; if (this.document) { ctx.meta.limited = this.document.limited; - ctx.meta.editable = ctx.editable; - } + ctx.meta.editable = this.isEditable || game.user.isGM; + ctx.meta.embedded = this.document.isEmbedded; + }; delete ctx.editable; return ctx; diff --git a/module/Apps/ItemSheets/AllItemSheetV1.mjs b/module/Apps/ItemSheets/AllItemSheetV1.mjs index 3ac26ba..0608fde 100644 --- a/module/Apps/ItemSheets/AllItemSheetV1.mjs +++ b/module/Apps/ItemSheets/AllItemSheetV1.mjs @@ -61,7 +61,7 @@ export class AllItemSheetV1 extends GenericAppMixin(HandlebarsApplicationMixin(I await super._processSubmitData(...args); if (this.document.system.forceRerender) { - await this.render(false); + await this.render(); }; }; // #endregion diff --git a/module/Apps/ItemSheets/ArmourSheet.mjs b/module/Apps/ItemSheets/ArmourSheet.mjs new file mode 100644 index 0000000..7570413 --- /dev/null +++ b/module/Apps/ItemSheets/ArmourSheet.mjs @@ -0,0 +1,135 @@ +import { filePath } from "../../consts.mjs"; +import { gameTerms } from "../../gameTerms.mjs"; +import { GenericAppMixin } from "../GenericApp.mjs"; + +const { HandlebarsApplicationMixin } = foundry.applications.api; +const { ItemSheetV2 } = foundry.applications.sheets; +const { getProperty, hasProperty, setProperty } = foundry.utils; + +export class ArmourSheet extends GenericAppMixin(HandlebarsApplicationMixin(ItemSheetV2)) { + + // #region Options + static DEFAULT_OPTIONS = { + classes: [ + `ripcrypt--item`, + `ArmourSheet`, + ], + position: { + width: `auto`, + height: `auto`, + }, + window: { + resizable: false, + }, + form: { + submitOnChange: true, + closeOnSubmit: false, + }, + }; + + static PARTS = { + header: { + template: filePath(`templates/Apps/partials/item-header.hbs`), + }, + content: { + template: filePath(`templates/Apps/ArmourSheet/content.hbs`), + }, + }; + // #endregion + + // #region Lifecycle + async _onRender() { + // remove the flag if it exists when we render the sheet + delete this.document?.system?.forceRerender; + }; + + /** + * Used to make it so that items that don't get updated because of the + * _preUpdate hook removing/changing the data submitted, can still get + * re-rendered when the diff is empty. If the document does get updated, + * this rerendering does not happen. + * + * @override + */ + async _processSubmitData(...args) { + await super._processSubmitData(...args); + + if (this.document.system.forceRerender) { + await this.render(); + }; + }; + + /** + * Customize how form data is extracted into an expanded object. + * @param {SubmitEvent|null} event The originating form submission event + * @param {HTMLFormElement} form The form element that was submitted + * @param {FormDataExtended} formData Processed data for the submitted form + * @returns {object} An expanded object of processed form data + * @throws {Error} Subclasses may throw validation errors here to prevent form submission + * @protected + */ + _processFormData(event, form, formData) { + const data = super._processFormData(event, form, formData); + + if (hasProperty(data, `system.location`)) { + let locations = getProperty(data, `system.location`); + locations = locations.filter(value => value != null); + setProperty(data, `system.location`, locations); + }; + + return data; + }; + // #endregion + + // #region Data Prep + async _preparePartContext(partId, _, opts) { + const ctx = await super._preparePartContext(partId, {}, opts); + + ctx.item = this.document; + ctx.system = this.document.system; + + switch (partId) { + case `content`: { + this._prepareContentContext(ctx, opts); + break; + }; + }; + + return ctx; + }; + + async _prepareContentContext(ctx) { + ctx.weights = [ + { + label: `RipCrypt.common.empty`, + value: null, + }, + ...Object.values(gameTerms.WeightRatings).map(opt => ({ + label: `RipCrypt.common.weightRatings.${opt}`, + value: opt, + })), + ]; + + ctx.accesses = [ + { + label: `RipCrypt.common.empty`, + value: ``, + }, + ...gameTerms.Access.map(opt => ({ + label: `RipCrypt.common.accessLevels.${opt}`, + value: opt, + })), + ]; + + ctx.protects = { + head: this.document.system.location.has(gameTerms.Anatomy.HEAD), + body: this.document.system.location.has(gameTerms.Anatomy.BODY), + arms: this.document.system.location.has(gameTerms.Anatomy.ARMS), + legs: this.document.system.location.has(gameTerms.Anatomy.LEGS), + }; + }; + // #endregion + + // #region Actions + // #endregion +}; diff --git a/module/Apps/components/ArmourSummary.mjs b/module/Apps/components/ArmourSummary.mjs new file mode 100644 index 0000000..15ddf16 --- /dev/null +++ b/module/Apps/components/ArmourSummary.mjs @@ -0,0 +1,56 @@ +import { filePath } from "../../consts.mjs"; +import { StyledShadowElement } from "./mixins/StyledShadowElement.mjs"; + +const { renderTemplate } = foundry.applications.handlebars; + +export class ArmourSummary extends StyledShadowElement(HTMLElement) { + static elementName = `armour-summary`; + static formAssociated = false; + + /* Stuff for the mixin to use */ + static _stylePath = `css/components/armour-summary.css`; + #container; + + get type() { + return this.getAttribute(`type`) ?? `hero`; + }; + + set type(newValue) { + this.setAttribute(`type`, newValue); + }; + + _mounted = false; + async connectedCallback() { + super.connectedCallback(); + if (this._mounted) { return }; + + /* + This converts all of the double-dash prefixed properties on the element to + CSS variables so that they don't all need to be provided by doing style="" + */ + for (const attrVar of this.attributes) { + if (attrVar.name?.startsWith(`var:`)) { + const prop = attrVar.name.replace(`var:`, ``); + this.style.setProperty(`--` + prop, attrVar.value); + }; + }; + + this.#container = document.createElement(`div`); + this.#container.classList = `person`; + + this.#container.innerHTML = await renderTemplate( + filePath(`templates/components/armour-summary.hbs`), + { type: this.type }, + ); + + this._shadow.appendChild(this.#container); + + this._mounted = true; + }; + + disconnectedCallback() { + super.disconnectedCallback(); + if (!this._mounted) { return }; + this._mounted = false; + }; +}; diff --git a/module/Apps/elements/Icon.mjs b/module/Apps/components/Icon.mjs similarity index 100% rename from module/Apps/elements/Icon.mjs rename to module/Apps/components/Icon.mjs diff --git a/module/Apps/elements/RipCryptBorder.mjs b/module/Apps/components/RipCryptBorder.mjs similarity index 100% rename from module/Apps/elements/RipCryptBorder.mjs rename to module/Apps/components/RipCryptBorder.mjs diff --git a/module/Apps/elements/_index.mjs b/module/Apps/components/_index.mjs similarity index 91% rename from module/Apps/elements/_index.mjs rename to module/Apps/components/_index.mjs index 3568481..8400462 100644 --- a/module/Apps/elements/_index.mjs +++ b/module/Apps/components/_index.mjs @@ -1,9 +1,11 @@ +import { ArmourSummary } from "./ArmourSummary.mjs"; import { Logger } from "../../utils/Logger.mjs"; import { RipCryptBorder } from "./RipCryptBorder.mjs"; import { RipCryptIcon } from "./Icon.mjs"; import { RipCryptSVGLoader } from "./svgLoader.mjs"; const components = [ + ArmourSummary, RipCryptIcon, RipCryptSVGLoader, RipCryptBorder, diff --git a/module/Apps/elements/mixins/StyledShadowElement.mjs b/module/Apps/components/mixins/StyledShadowElement.mjs similarity index 98% rename from module/Apps/elements/mixins/StyledShadowElement.mjs rename to module/Apps/components/mixins/StyledShadowElement.mjs index e5ef291..37f81d1 100644 --- a/module/Apps/elements/mixins/StyledShadowElement.mjs +++ b/module/Apps/components/mixins/StyledShadowElement.mjs @@ -51,7 +51,8 @@ export function StyledShadowElement(Base) { const stylePath = this.constructor._stylePath; if (this.constructor._styles.has(stylePath)) { this._style.innerHTML = this.constructor._styles.get(stylePath); - } else { + } + else { fetch(`./systems/${game.system.id}/templates/${stylePath}`) .then(r => r.text()) .then(t => { diff --git a/module/Apps/elements/svgLoader.mjs b/module/Apps/components/svgLoader.mjs similarity index 100% rename from module/Apps/elements/svgLoader.mjs rename to module/Apps/components/svgLoader.mjs diff --git a/module/Apps/utils.mjs b/module/Apps/utils.mjs index 7c55ec4..47f8f01 100644 --- a/module/Apps/utils.mjs +++ b/module/Apps/utils.mjs @@ -11,7 +11,7 @@ export async function createItemFromElement(target, { parent } = {}) { const type = data.defaultItemType; await Item.createDialog( { type }, - { parent }, + { parent, showEquipPrompt: false }, { types, folders: [], @@ -40,7 +40,7 @@ export async function deleteItemFromElement(target) { const itemId = itemEl.dataset.itemId; if (!itemId) { return }; const item = await fromUuid(itemId); - item.delete(); + item.deleteDialog(); }; /** diff --git a/module/consts.mjs b/module/consts.mjs index 405707e..ee88a31 100644 --- a/module/consts.mjs +++ b/module/consts.mjs @@ -42,9 +42,11 @@ export function toBoolean(val) { export function documentSorter(a, b) { if (!a && !b) { return 0; - } else if (!a) { + } + else if (!a) { return 1; - } else if (!b) { + } + else if (!b) { return -1; }; diff --git a/module/data/Actor/Entity.mjs b/module/data/Actor/Entity.mjs index 7a424d9..89f2b7f 100644 --- a/module/data/Actor/Entity.mjs +++ b/module/data/Actor/Entity.mjs @@ -155,6 +155,11 @@ export class EntityData extends foundry.abstract.TypeDataModel { }; // #region Getters + get equippedWeapons() { + const weapons = this.parent.itemTypes.weapon; + return weapons.filter(w => w.system.equipped); + }; + get equippedArmour() { const armours = this.parent.itemTypes.armour; const slots = Object.fromEntries( diff --git a/module/data/Item/Armour.mjs b/module/data/Item/Armour.mjs index 2669b4c..f2a1b0a 100644 --- a/module/data/Item/Armour.mjs +++ b/module/data/Item/Armour.mjs @@ -4,12 +4,13 @@ import { localizer } from "../../utils/Localizer.mjs"; import { Logger } from "../../utils/Logger.mjs"; import { requiredInteger } from "../helpers.mjs"; +const { diffObject, getProperty, setProperty } = foundry.utils; +const { DialogV2 } = foundry.applications.api; const { fields } = foundry.data; -const { hasProperty, diffObject, mergeObject } = foundry.utils; /** Used for Armour and Shields */ export class ArmourData extends CommonItemData { - // MARK: Schema + // #region Schema static defineSchema() { return { ...super.defineSchema(), @@ -19,16 +20,16 @@ export class ArmourData extends CommonItemData { blank: false, trim: true, nullable: false, + required: true, options: Object.values(gameTerms.Anatomy), }), { nullable: false, - required: true, + initial: [], }, ), equipped: new fields.BooleanField({ initial: false, - required: true, nullable: false, }), weight: new fields.StringField({ @@ -39,27 +40,30 @@ export class ArmourData extends CommonItemData { }), }; }; - - // MARK: Base Data - prepareBaseData() { - super.prepareBaseData(); - }; - - // MARK: Derived Data - prepareDerivedData() { - super.prepareDerivedData(); - }; + // #endregion Schema // #region Lifecycle + async _preCreate(item, options) { + const showEquipPrompt = options.showEquipPrompt ?? true; + if (showEquipPrompt && this.parent.isEmbedded && this._canEquip()) { + const shouldEquip = await DialogV2.confirm({ + window: { title: `Equip Item?` }, + content: `Do you want to equip ${item.name}?`, + }); + if (shouldEquip) { + this.updateSource({ "equipped": true }); + }; + }; + }; + async _preUpdate(changes, options, user) { - // return false if (options.force && game.settings.get(`ripcrypt`, `devMode`)) { return }; // Ensure changes is a diffed object const diff = diffObject(this.parent._source, changes); let valid = await super._preUpdate(changes, options, user); - if (hasProperty(diff, `system.equipped`) && !this._canEquip()) { + if (getProperty(diff, `system.equipped`) && !this._canEquip()) { ui.notifications.error( localizer( `RipCrypt.notifs.error.cannot-equip`, @@ -69,9 +73,7 @@ export class ArmourData extends CommonItemData { ); // Don't stop the update, but don't allow changing the equipped status - mergeObject(changes, { - "system.equipped": false, - }); + setProperty(changes, `system.equipped`, false); // Set a flag so that we can tell the sheet that it needs to rerender this.forceRerender = true; @@ -79,8 +81,13 @@ export class ArmourData extends CommonItemData { return valid; }; + // #endregion Lifecycle - /** Used to tell the preUpdate logic whether or not to prevent the */ + // #region Helpers + /** + * Used to tell the preUpdate logic whether or not to prevent the item from + * being equipped or not. + */ _canEquip() { const parent = this.parent; if (!parent.isEmbedded || !(parent.parent instanceof Actor)) { @@ -94,7 +101,7 @@ export class ArmourData extends CommonItemData { }; const slots = parent.parent.system.equippedArmour ?? {}; - Logger.debug(`slots`, slots); + for (const locationTag of this.location) { if (slots[locationTag.toLowerCase()] != null) { Logger.error(`Unable to equip multiple items in the same slot`); @@ -103,97 +110,9 @@ export class ArmourData extends CommonItemData { }; return true; }; - // #endregion - // #region Getters get locationString() { return [...this.location].join(`, `); }; - // #endregion - - // #region Sheet Data - getFormFields(_ctx) { - const fields = [ - { - id: `quantity`, - type: `integer`, - label: `RipCrypt.common.quantity`, - path: `system.quantity`, - value: this.quantity, - min: 0, - }, - { - id: `access`, - type: `dropdown`, - label: `RipCrypt.common.access`, - path: `system.access`, - value: this.access, - limited: false, - options: [ - { - label: `RipCrypt.common.empty`, - value: ``, - }, - ...gameTerms.Access.map(opt => ({ - label: `RipCrypt.common.accessLevels.${opt}`, - value: opt, - })), - ], - }, - { - id: `cost`, - type: `cost`, - label: `RipCrypt.common.cost`, - gold: this.cost.gold, - silver: this.cost.silver, - copper: this.cost.copper, - }, - { - id: `weight`, - type: `dropdown`, - label: `RipCrypt.common.weightRating`, - path: `system.weight`, - value: this.weight, - options: [ - { - label: `RipCrypt.common.empty`, - value: null, - }, - ...Object.values(gameTerms.WeightRatings).map(opt => ({ - label: `RipCrypt.common.weightRatings.${opt}`, - value: opt, - })), - ], - }, - { - id: `location`, - type: `string-set`, - label: `RipCrypt.common.location`, - placeholder: `RipCrypt.Apps.location-placeholder`, - path: `system.location`, - value: this.locationString, - }, - { - id: `protection`, - type: `integer`, - label: `RipCrypt.common.protection`, - value: this.protection, - path: `system.protection`, - min: 0, - }, - ]; - - if (this.parent.isEmbedded) { - fields.push({ - id: `equipped`, - type: `boolean`, - label: `RipCrypt.common.equipped`, - value: this.equipped, - path: `system.equipped`, - }); - }; - - return fields; - }; - // #endregion + // #endregion Helpers }; diff --git a/module/data/Item/Weapon.mjs b/module/data/Item/Weapon.mjs index a4b77ff..ec35f29 100644 --- a/module/data/Item/Weapon.mjs +++ b/module/data/Item/Weapon.mjs @@ -2,12 +2,14 @@ import { barAttribute, optionalInteger, requiredInteger } from "../helpers.mjs"; import { CommonItemData } from "./Common.mjs"; import { gameTerms } from "../../gameTerms.mjs"; import { localizer } from "../../utils/Localizer.mjs"; +import { Logger } from "../../utils/Logger.mjs"; +const { diffObject, getProperty, setProperty } = foundry.utils; +const { DialogV2 } = foundry.applications.api; const { fields } = foundry.data; -const { hasProperty, mergeObject } = foundry.utils; export class WeaponData extends CommonItemData { - // MARK: Schema + // #region Schema static defineSchema() { return { ...super.defineSchema(), @@ -41,39 +43,69 @@ export class WeaponData extends CommonItemData { }), }; }; - - // MARK: Base Data - prepareBaseData() { - super.prepareBaseData(); - }; - - // MARK: Derived Data - prepareDerivedData() { - super.prepareDerivedData(); - }; + // #endregion Schema // #region Lifecycle + async _preCreate(item, options) { + const showEquipPrompt = options.showEquipPrompt ?? true; + if (showEquipPrompt && this.parent.isEmbedded && this._canEquip()) { + const shouldEquip = await DialogV2.confirm({ + window: { title: `Equip Item?` }, + content: `Do you want to equip ${item.name}?`, + }); + if (shouldEquip) { + this.updateSource({ "equipped": true }); + }; + }; + }; + + /** + * + * @param {*} changes The expanded object that was used for the update + * @param {*} options + * @param {*} user + * @returns + */ async _preUpdate(changes, options, user) { if (options.force && game.settings.get(`ripcrypt`, `devMode`)) { return }; + + const diff = diffObject(this.parent._source, changes); let valid = super._preUpdate(changes, options, user); - if (hasProperty(changes, `system.equipped`) && !this.parent.isEmbedded) { + if (getProperty(diff, `system.equipped`) && !this._canEquip()) { ui.notifications.error(localizer( - `RipCrypt.notifs.error.cannot-equip-not-embedded`, + `RipCrypt.notifs.error.cannot-equip`, { itemType: `@TYPES.Item.${this.parent.type}` }, )); - mergeObject( - changes, - { "-=system.equipped": null }, - { inplace: true, performDeletions: true }, - ); - return false; + + // Don't stop the update, but don't allow changing the equipped status + setProperty(changes, `system.equipped`, false); + + // Set a flag so that we can tell the sheet that it needs to rerender + this.forceRerender = true; }; return valid; }; - // #endregion + // #endregion Lifecycle + + // #region Helpers + /** + * Used to tell the preUpdate logic whether or not to prevent the item from + * being equipped or not. + */ + _canEquip() { + const parent = this.parent; + if (!parent.isEmbedded || !(parent.parent instanceof Actor)) { + Logger.error(`Unable to equip item when it's not embedded`); + return false; + }; + const actor = this.parent.parent.system; + if (actor.equippedWeapons?.length >= actor.limit.weapons) { + return false; + }; + return true; + }; - // #region Getters get traitString() { return [...this.traits].join(`, `); }; @@ -84,7 +116,7 @@ export class WeaponData extends CommonItemData { }; return String(this.range.short ?? this.range.long ?? ``); }; - // #endregion + // #endregion Helpers // #region Sheet Data async getFormFields(_ctx) { @@ -167,7 +199,8 @@ export class WeaponData extends CommonItemData { value: this.range.long, }, }); - } else { + } + else { fields.push({ id: `short-range`, type: `integer`, @@ -225,5 +258,5 @@ export class WeaponData extends CommonItemData { return fields; }; - // #endregion + // #endregion Sheet Data }; diff --git a/module/dice/CryptDie.mjs b/module/dice/CryptDie.mjs index 9f304d2..4da7ce7 100644 --- a/module/dice/CryptDie.mjs +++ b/module/dice/CryptDie.mjs @@ -38,7 +38,8 @@ export class CryptDie extends Die { if (almostCrypted) { this.ripCryptState = `crypted`; break; - } else { + } + else { almostCrypted = true; } } diff --git a/module/documents/combat.mjs b/module/documents/combat.mjs index 0e3936f..f2aeb4b 100644 --- a/module/documents/combat.mjs +++ b/module/documents/combat.mjs @@ -16,7 +16,8 @@ export class RipCryptCombat extends Combat { if (groups.has(groupKey)) { groups.get(groupKey).push(combatant); - } else { + } + else { groups.set(groupKey, [combatant]); }; }; @@ -129,7 +130,8 @@ export class RipCryptCombat extends Combat { const currentToken = this.combatant?.token?._object; if (!tokenGroup && currentToken) { currentToken.renderFlags.set({refreshTurnMarker: true}); - } else { + } + else { const group = this.customGroups.get(tokenGroup) ?? []; for (const combatant of group) { combatant.token?._object?.renderFlags.set({ refreshTurnMarker: true }); diff --git a/module/documents/combatant.mjs b/module/documents/combatant.mjs index 0594db5..128f042 100644 --- a/module/documents/combatant.mjs +++ b/module/documents/combatant.mjs @@ -28,7 +28,8 @@ export class RipCryptCombatant extends Combatant { const disposition = this.disposition; if (disposition === `unknown`) { total += 0.25; - } else if (whoFirst !== disposition) { + } + else if (whoFirst !== disposition) { total += 0.5; }; }; diff --git a/module/documents/token.mjs b/module/documents/token.mjs index c4913fe..9492339 100644 --- a/module/documents/token.mjs +++ b/module/documents/token.mjs @@ -26,7 +26,8 @@ export class RipCryptToken extends Token { }; canvas.tokens.turnMarkers.add(this); this.turnMarker.draw(); - } else if (this.turnMarker) { + } + else if (this.turnMarker) { canvas.tokens.turnMarkers.delete(this); this.turnMarker.destroy(); this.turnMarker = null; diff --git a/module/hooks/init.mjs b/module/hooks/init.mjs index 645a5be..28c4fd9 100644 --- a/module/hooks/init.mjs +++ b/module/hooks/init.mjs @@ -1,5 +1,6 @@ // Applications import { AllItemSheetV1 } from "../Apps/ItemSheets/AllItemSheetV1.mjs"; +import { ArmourSheet } from "../Apps/ItemSheets/ArmourSheet.mjs"; import { CombinedHeroSheet } from "../Apps/ActorSheets/CombinedHeroSheet.mjs"; import { CraftCardV1 } from "../Apps/ActorSheets/CraftCardV1.mjs"; import { DelveDiceHUD } from "../Apps/DelveDiceHUD.mjs"; @@ -30,14 +31,14 @@ import { RipCryptToken } from "../documents/token.mjs"; // Misc import helpers from "../handlebarHelpers/_index.mjs"; import { Logger } from "../utils/Logger.mjs"; -import { registerCustomComponents } from "../Apps/elements/_index.mjs"; +import { registerCustomComponents } from "../Apps/components/_index.mjs"; import { registerDevSettings } from "../settings/devSettings.mjs"; import { registerMetaSettings } from "../settings/metaSettings.mjs"; +import { registerSockets } from "../sockets/_index.mjs"; import { registerUserSettings } from "../settings/userSettings.mjs"; import { registerWorldSettings } from "../settings/worldSettings.mjs"; const { Items, Actors } = foundry.documents.collections; -const { ItemSheet, ActorSheet } = foundry.appv1.sheets; Hooks.once(`init`, () => { Logger.log(`Initializing`); @@ -74,10 +75,6 @@ Hooks.once(`init`, () => { // #endregion // #region Sheets - // Unregister core sheets - Items.unregisterSheet(`core`, ItemSheet); - Actors.unregisterSheet(`core`, ActorSheet); - // #region Actors Actors.registerSheet(game.system.id, CombinedHeroSheet, { makeDefault: true, @@ -114,6 +111,16 @@ Hooks.once(`init`, () => { label: `RipCrypt.sheet-names.AllItemsSheetV1`, themes: AllItemSheetV1.themes, }); + + Items.registerSheet(game.system.id, ArmourSheet, { + makeDefault: true, + types: [`armour`, `shield`], + label: `RipCrypt.sheet-names.ArmourSheet`, + themes: ArmourSheet.themes, + }); + Items.unregisterSheet(game.system.id, AllItemSheetV1, { + types: [`armour`, `shield`], + }); // #endregion // #endregion @@ -121,6 +128,7 @@ Hooks.once(`init`, () => { CONFIG.Actor.trackableAttributes.hero = HeroData.trackableAttributes; // #endregion + registerSockets(); registerCustomComponents(); Handlebars.registerHelper(helpers); }); diff --git a/module/hooks/ready.mjs b/module/hooks/ready.mjs index 63223d7..e77e0e7 100644 --- a/module/hooks/ready.mjs +++ b/module/hooks/ready.mjs @@ -6,17 +6,18 @@ Hooks.once(`ready`, () => { let defaultTab = game.settings.get(`ripcrypt`, `defaultTab`); if (defaultTab) { - if (!ui.sidebar?.TABS?.[defaultTab]) { - Logger.error(`Couldn't find a sidebar tab with ID:`, defaultTab); - } else { + try { Logger.debug(`Switching sidebar tab to:`, defaultTab); - ui.sidebar.activateTab(defaultTab); + ui.sidebar.changeTab(defaultTab, `primary`); + } + catch { + Logger.error(`Failed to change to sidebar tab:`, defaultTab); }; }; if (game.settings.get(`ripcrypt`, `devMode`)) { ui.sidebar.expand(); - if (game.paused) { game.togglePause() }; + if (game.paused) { game.togglePause(false, { broadcast: true }) }; }; ui.delveDice.render({ force: true }); @@ -28,7 +29,7 @@ Hooks.once(`ready`, () => { combatConfig.turnMarker.src = filePath(`assets/turn-marker.png`); combatConfig.turnMarker.animation = `spinPulse`; game.settings.set(`core`, `combatTrackerConfig`, combatConfig); - } + }; game.settings.set(`ripcrypt`, `firstLoadFinished`, true); }); diff --git a/module/settings/worldSettings.mjs b/module/settings/worldSettings.mjs index ca095ae..ac1643c 100644 --- a/module/settings/worldSettings.mjs +++ b/module/settings/worldSettings.mjs @@ -39,4 +39,14 @@ export function registerWorldSettings() { }, }), }); + + game.settings.register(`ripcrypt`, `allowUpdateSandsSocket`, { + name: `RipCrypt.setting.allowUpdateSandsSocket.name`, + hint: `RipCrypt.setting.allowUpdateSandsSocket.hint`, + scope: `world`, + config: true, + requiresReload: false, + type: Boolean, + default: true, + }); }; diff --git a/module/sockets/_index.mjs b/module/sockets/_index.mjs new file mode 100644 index 0000000..bcb2b5e --- /dev/null +++ b/module/sockets/_index.mjs @@ -0,0 +1,29 @@ +import { localizer } from "../utils/Localizer.mjs"; +import { Logger } from "../utils/Logger.mjs"; +import { notify } from "./notify.mjs"; +import { updateSands } from "./updateSands.mjs"; + +const events = { + notify, + updateSands, +}; + +export function registerSockets() { + Logger.info(`Setting up socket listener`); + + game.socket.on(`system.ripcrypt`, (data, userID) => { + const { event, payload } = data ?? {}; + if (event == null || payload === undefined) { + ui.notifications.error(localizer(`RipCrypt.notifs.error.invalid-socket`)); + return; + }; + + if (events[event] == null) { + ui.notifications.error(localizer(`RipCrypt.notifs.error.unknown-socket-event`, { event })); + return; + }; + + const user = game.users.get(userID); + events[event](payload, user); + }); +}; diff --git a/module/sockets/notify.mjs b/module/sockets/notify.mjs new file mode 100644 index 0000000..072e5af --- /dev/null +++ b/module/sockets/notify.mjs @@ -0,0 +1,56 @@ +import { localizer } from "../utils/Localizer.mjs"; + +export function notify(payload) { + // #region Payload Validity + const { + message, + users = [], + type = `info`, + permanent = false, + } = payload; + + if (!message) { + ui.notifications.error(localizer( + `RipCrypt.notifs.error.malformed-socket-payload`, + { + event: `notify`, + details: `A message must be provided`, + }, + )); + return; + }; + + if (users && !Array.isArray(users)) { + ui.notifications.error(localizer( + `RipCrypt.notifs.error.malformed-socket-payload`, + { + event: `notify`, + details: `"users" must be an array of user IDs`, + }, + )); + return; + }; + + if (![`info`, `error`, `success`].includes(type)) { + ui.notifications.error(localizer( + `RipCrypt.notifs.error.malformed-socket-payload`, + { + event: `notify`, + details: `An invalid notification type was provided.`, + }, + )); + return; + } + // #endregion Payload Validity + + // Act + if (users.length === 0 || users.includes(game.user.id)) { + ui.notifications[type]?.( + localizer(message), + { + console: false, + permanent, + }, + ); + }; +}; diff --git a/module/sockets/updateSands.mjs b/module/sockets/updateSands.mjs new file mode 100644 index 0000000..8560b6d --- /dev/null +++ b/module/sockets/updateSands.mjs @@ -0,0 +1,38 @@ +import { clamp } from "../utils/clamp.mjs"; +import { localizer } from "../utils/Localizer.mjs"; + +export function updateSands(payload) { + if (!game.user.isActiveGM) { return }; + if (!game.settings.get(game.system.id, `allowUpdateSandsSocket`)) { return }; + + // Assert payload validity + const { value, delta } = payload; + if (value == null && delta == null) { + ui.notifications.error(localizer( + `RipCrypt.notifs.error.malformed-socket-payload`, + { + event: `updateSands`, + details: `Either value or delta must be provided`, + }, + )); + return; + }; + + // Take action + if (value != null) { + const initial = game.settings.get(game.system.id, `sandsOfFateInitial`); + let sands = clamp(0, value, initial); + if (sands === 0) { + ui.delveDice.alertCrypticEvent(); + sands = initial; + }; + game.settings.set( + game.system.id, + `sandsOfFate`, + sands, + ); + } + else if (delta != null) { + ui.delveDice.sandsOfFateDelta(delta); + }; +}; diff --git a/module/utils/clamp.mjs b/module/utils/clamp.mjs new file mode 100644 index 0000000..94cac4e --- /dev/null +++ b/module/utils/clamp.mjs @@ -0,0 +1,3 @@ +export function clamp(min, ideal, max) { + return Math.max(min, Math.min(ideal, max)); +}; diff --git a/package-lock.json b/package-lock.json index 9384e26..af1a200 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "@eslint/js": "^9.16.0", "@foundryvtt/foundryvtt-cli": "^1.0.3", "@stylistic/eslint-plugin": "^2.12.0", + "dotenv": "^17.2.3", "eslint": "^9.16.0" } }, @@ -775,6 +776,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.0.tgz", diff --git a/package.json b/package.json index 9b335a7..5fa77f1 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,13 @@ "@eslint/js": "^9.16.0", "@foundryvtt/foundryvtt-cli": "^1.0.3", "@stylistic/eslint-plugin": "^2.12.0", + "dotenv": "^17.2.3", "eslint": "^9.16.0" }, "scripts": { + "data:build": "node scripts/buildCompendia.mjs", + "data:extract": "node scripts/extractCompendia.mjs", + "link": "node scripts/linkFoundry.mjs", "lint": "eslint --fix", "lint:nofix": "eslint" } diff --git a/packs/protection/_source/Armour_pZxc6QLgVWfnZlf7.json b/packs/protection/_source/Armour_pZxc6QLgVWfnZlf7.json new file mode 100644 index 0000000..6f80750 --- /dev/null +++ b/packs/protection/_source/Armour_pZxc6QLgVWfnZlf7.json @@ -0,0 +1,23 @@ +{ + "type": "Item", + "folder": null, + "name": "Armour", + "color": "#04262a", + "sorting": "m", + "_id": "pZxc6QLgVWfnZlf7", + "description": "", + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994081362, + "modifiedTime": 1759994081362, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!folders!pZxc6QLgVWfnZlf7" +} diff --git a/packs/protection/_source/Breastplate_KQ6uyTPUOHuMTxDF.json b/packs/protection/_source/Breastplate_KQ6uyTPUOHuMTxDF.json new file mode 100644 index 0000000..75dd4a1 --- /dev/null +++ b/packs/protection/_source/Breastplate_KQ6uyTPUOHuMTxDF.json @@ -0,0 +1,41 @@ +{ + "folder": "BsNUpCnwmlhOWBhZ", + "name": "Breastplate", + "type": "armour", + "_id": "KQ6uyTPUOHuMTxDF", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 90, + "copper": null + }, + "protection": 3, + "location": [ + "body" + ], + "equipped": false, + "weight": "heavy", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994459142, + "modifiedTime": 1759994468351, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!KQ6uyTPUOHuMTxDF" +} diff --git a/packs/protection/_source/Heavy_BsNUpCnwmlhOWBhZ.json b/packs/protection/_source/Heavy_BsNUpCnwmlhOWBhZ.json new file mode 100644 index 0000000..225a22c --- /dev/null +++ b/packs/protection/_source/Heavy_BsNUpCnwmlhOWBhZ.json @@ -0,0 +1,21 @@ +{ + "type": "Item", + "folder": "pZxc6QLgVWfnZlf7", + "name": "Heavy", + "color": "#06393f", + "sorting": "a", + "_id": "BsNUpCnwmlhOWBhZ", + "description": "", + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "lastModifiedBy": null + }, + "_key": "!folders!BsNUpCnwmlhOWBhZ" +} diff --git a/packs/protection/_source/Heavy_Shields_uUrCwjxV6Ihisb6V.json b/packs/protection/_source/Heavy_Shields_uUrCwjxV6Ihisb6V.json new file mode 100644 index 0000000..69d4a46 --- /dev/null +++ b/packs/protection/_source/Heavy_Shields_uUrCwjxV6Ihisb6V.json @@ -0,0 +1,44 @@ +{ + "folder": "RXPJBkzVxFnoT3Tm", + "name": "Heavy Shields", + "type": "shield", + "_id": "uUrCwjxV6Ihisb6V", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 50, + "copper": null + }, + "protection": 1, + "location": [ + "head", + "body", + "arms", + "legs" + ], + "equipped": false, + "weight": "heavy", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994801184, + "modifiedTime": 1759994810086, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!uUrCwjxV6Ihisb6V" +} diff --git a/packs/protection/_source/Leather_Cap_JMkV8kMnCXhW5KDh.json b/packs/protection/_source/Leather_Cap_JMkV8kMnCXhW5KDh.json new file mode 100644 index 0000000..c7db6f2 --- /dev/null +++ b/packs/protection/_source/Leather_Cap_JMkV8kMnCXhW5KDh.json @@ -0,0 +1,41 @@ +{ + "folder": "HRwiz1c1ZcQyPu4z", + "name": "Leather Cap", + "type": "armour", + "_id": "JMkV8kMnCXhW5KDh", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 10, + "copper": null + }, + "protection": 1, + "location": [ + "head" + ], + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994118194, + "modifiedTime": 1759994130845, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!JMkV8kMnCXhW5KDh" +} diff --git a/packs/protection/_source/Leather__Hide_Bracers_nz4DXXR4iU9CeMRA.json b/packs/protection/_source/Leather__Hide_Bracers_nz4DXXR4iU9CeMRA.json new file mode 100644 index 0000000..509e0e7 --- /dev/null +++ b/packs/protection/_source/Leather__Hide_Bracers_nz4DXXR4iU9CeMRA.json @@ -0,0 +1,41 @@ +{ + "folder": "HRwiz1c1ZcQyPu4z", + "name": "Leather, Hide Bracers", + "type": "armour", + "_id": "nz4DXXR4iU9CeMRA", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 10, + "copper": null + }, + "protection": 1, + "location": [ + "arms" + ], + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994170968, + "modifiedTime": 1759994180395, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!nz4DXXR4iU9CeMRA" +} diff --git a/packs/protection/_source/Leather__Hide_Jacket_zMyxSJ6VpaH3ddOO.json b/packs/protection/_source/Leather__Hide_Jacket_zMyxSJ6VpaH3ddOO.json new file mode 100644 index 0000000..f382b54 --- /dev/null +++ b/packs/protection/_source/Leather__Hide_Jacket_zMyxSJ6VpaH3ddOO.json @@ -0,0 +1,41 @@ +{ + "folder": "HRwiz1c1ZcQyPu4z", + "name": "Leather, Hide Jacket", + "type": "armour", + "_id": "zMyxSJ6VpaH3ddOO", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 20, + "copper": null + }, + "protection": 1, + "location": [ + "body" + ], + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994151324, + "modifiedTime": 1759994160761, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!zMyxSJ6VpaH3ddOO" +} diff --git a/packs/protection/_source/Leather__Hide_Leggings_14Omu9q2sMxW8GWB.json b/packs/protection/_source/Leather__Hide_Leggings_14Omu9q2sMxW8GWB.json new file mode 100644 index 0000000..8c9a9c3 --- /dev/null +++ b/packs/protection/_source/Leather__Hide_Leggings_14Omu9q2sMxW8GWB.json @@ -0,0 +1,41 @@ +{ + "folder": "HRwiz1c1ZcQyPu4z", + "name": "Leather, Hide Leggings", + "type": "armour", + "_id": "14Omu9q2sMxW8GWB", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 20, + "copper": null + }, + "protection": 1, + "location": [ + "legs" + ], + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994190989, + "modifiedTime": 1759994198011, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!14Omu9q2sMxW8GWB" +} diff --git a/packs/protection/_source/Light_HRwiz1c1ZcQyPu4z.json b/packs/protection/_source/Light_HRwiz1c1ZcQyPu4z.json new file mode 100644 index 0000000..bb9b437 --- /dev/null +++ b/packs/protection/_source/Light_HRwiz1c1ZcQyPu4z.json @@ -0,0 +1,21 @@ +{ + "type": "Item", + "folder": "pZxc6QLgVWfnZlf7", + "name": "Light", + "color": "#06393f", + "sorting": "a", + "_id": "HRwiz1c1ZcQyPu4z", + "description": "", + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "lastModifiedBy": null + }, + "_key": "!folders!HRwiz1c1ZcQyPu4z" +} diff --git a/packs/protection/_source/Light_Shields_a6vPAa25z8L9t79K.json b/packs/protection/_source/Light_Shields_a6vPAa25z8L9t79K.json new file mode 100644 index 0000000..e04bc0c --- /dev/null +++ b/packs/protection/_source/Light_Shields_a6vPAa25z8L9t79K.json @@ -0,0 +1,42 @@ +{ + "folder": "RXPJBkzVxFnoT3Tm", + "name": "Light Shields", + "type": "shield", + "_id": "a6vPAa25z8L9t79K", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 20, + "copper": null + }, + "protection": 1, + "location": [ + "head", + "arms" + ], + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994549164, + "modifiedTime": 1759994761998, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!a6vPAa25z8L9t79K" +} diff --git a/packs/protection/_source/Mail__Link__Scale_Coat_Sr40RFsPr2M0bTKK.json b/packs/protection/_source/Mail__Link__Scale_Coat_Sr40RFsPr2M0bTKK.json new file mode 100644 index 0000000..1c008b2 --- /dev/null +++ b/packs/protection/_source/Mail__Link__Scale_Coat_Sr40RFsPr2M0bTKK.json @@ -0,0 +1,42 @@ +{ + "folder": "cKN149ZGLqfyt0oi", + "name": "Mail, Link, Scale Coat", + "type": "armour", + "_id": "Sr40RFsPr2M0bTKK", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 180, + "copper": null + }, + "protection": 2, + "location": [ + "body", + "arms" + ], + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994257751, + "modifiedTime": 1759994294312, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!Sr40RFsPr2M0bTKK" +} diff --git a/packs/protection/_source/Mail__Link__Scale_Coif_HfG5Doxf7576Jgbt.json b/packs/protection/_source/Mail__Link__Scale_Coif_HfG5Doxf7576Jgbt.json new file mode 100644 index 0000000..708afd3 --- /dev/null +++ b/packs/protection/_source/Mail__Link__Scale_Coif_HfG5Doxf7576Jgbt.json @@ -0,0 +1,41 @@ +{ + "folder": "cKN149ZGLqfyt0oi", + "name": "Mail, Link, Scale Coif", + "type": "armour", + "_id": "HfG5Doxf7576Jgbt", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 180, + "copper": null + }, + "protection": 2, + "location": [ + "head" + ], + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994210701, + "modifiedTime": 1759994221462, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!HfG5Doxf7576Jgbt" +} diff --git a/packs/protection/_source/Mail__Link__Scale_Leggings_YBpElIVQ534pm3Mf.json b/packs/protection/_source/Mail__Link__Scale_Leggings_YBpElIVQ534pm3Mf.json new file mode 100644 index 0000000..e1d45ce --- /dev/null +++ b/packs/protection/_source/Mail__Link__Scale_Leggings_YBpElIVQ534pm3Mf.json @@ -0,0 +1,41 @@ +{ + "folder": "cKN149ZGLqfyt0oi", + "name": "Mail, Link, Scale Leggings", + "type": "armour", + "_id": "YBpElIVQ534pm3Mf", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 200, + "copper": null + }, + "protection": 2, + "location": [ + "legs" + ], + "equipped": false, + "weight": null, + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994280754, + "modifiedTime": 1759994424980, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!YBpElIVQ534pm3Mf" +} diff --git a/packs/protection/_source/Mail__Link__Scale_Shirt_wab6Bo8ngar4mBCN.json b/packs/protection/_source/Mail__Link__Scale_Shirt_wab6Bo8ngar4mBCN.json new file mode 100644 index 0000000..766f79f --- /dev/null +++ b/packs/protection/_source/Mail__Link__Scale_Shirt_wab6Bo8ngar4mBCN.json @@ -0,0 +1,41 @@ +{ + "folder": "cKN149ZGLqfyt0oi", + "name": "Mail, Link, Scale Shirt", + "type": "armour", + "_id": "wab6Bo8ngar4mBCN", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 90, + "copper": null + }, + "protection": 2, + "location": [ + "body" + ], + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994235204, + "modifiedTime": 1759994246578, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!wab6Bo8ngar4mBCN" +} diff --git a/packs/protection/_source/Modest_Shields_fyL8LZ8jpEQbjpM2.json b/packs/protection/_source/Modest_Shields_fyL8LZ8jpEQbjpM2.json new file mode 100644 index 0000000..5f40713 --- /dev/null +++ b/packs/protection/_source/Modest_Shields_fyL8LZ8jpEQbjpM2.json @@ -0,0 +1,43 @@ +{ + "folder": "RXPJBkzVxFnoT3Tm", + "name": "Modest Shields", + "type": "shield", + "_id": "fyL8LZ8jpEQbjpM2", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 30, + "copper": null + }, + "protection": 1, + "location": [ + "head", + "body", + "arms" + ], + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994777609, + "modifiedTime": 1759994784898, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!fyL8LZ8jpEQbjpM2" +} diff --git a/packs/protection/_source/Modest_cKN149ZGLqfyt0oi.json b/packs/protection/_source/Modest_cKN149ZGLqfyt0oi.json new file mode 100644 index 0000000..0df0b4f --- /dev/null +++ b/packs/protection/_source/Modest_cKN149ZGLqfyt0oi.json @@ -0,0 +1,21 @@ +{ + "type": "Item", + "folder": "pZxc6QLgVWfnZlf7", + "name": "Modest", + "color": "#06393f", + "sorting": "a", + "_id": "cKN149ZGLqfyt0oi", + "description": "", + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "lastModifiedBy": null + }, + "_key": "!folders!cKN149ZGLqfyt0oi" +} diff --git a/packs/protection/_source/Plate_Bracers_e8JRJn5Blw3UrvnW.json b/packs/protection/_source/Plate_Bracers_e8JRJn5Blw3UrvnW.json new file mode 100644 index 0000000..b14cd65 --- /dev/null +++ b/packs/protection/_source/Plate_Bracers_e8JRJn5Blw3UrvnW.json @@ -0,0 +1,42 @@ +{ + "folder": "BsNUpCnwmlhOWBhZ", + "name": "Plate Bracers", + "type": "armour", + "_id": "e8JRJn5Blw3UrvnW", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 180, + "copper": null + }, + "protection": 1, + "location": [ + "body", + "arms" + ], + "equipped": false, + "weight": "heavy", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994478040, + "modifiedTime": 1759994486947, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!e8JRJn5Blw3UrvnW" +} diff --git a/packs/protection/_source/Plate_Leggings_v1y4RKGad2IXOu5e.json b/packs/protection/_source/Plate_Leggings_v1y4RKGad2IXOu5e.json new file mode 100644 index 0000000..ea89641 --- /dev/null +++ b/packs/protection/_source/Plate_Leggings_v1y4RKGad2IXOu5e.json @@ -0,0 +1,41 @@ +{ + "folder": "BsNUpCnwmlhOWBhZ", + "name": "Plate Leggings", + "type": "armour", + "_id": "v1y4RKGad2IXOu5e", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 200, + "copper": null + }, + "protection": 3, + "location": [ + "legs" + ], + "equipped": false, + "weight": "heavy", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994497119, + "modifiedTime": 1759994506514, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!v1y4RKGad2IXOu5e" +} diff --git a/packs/protection/_source/Ring_Coif__Helm_Z4NTsrX63JNjjZ8Z.json b/packs/protection/_source/Ring_Coif__Helm_Z4NTsrX63JNjjZ8Z.json new file mode 100644 index 0000000..072f340 --- /dev/null +++ b/packs/protection/_source/Ring_Coif__Helm_Z4NTsrX63JNjjZ8Z.json @@ -0,0 +1,41 @@ +{ + "folder": "BsNUpCnwmlhOWBhZ", + "name": "Ring Coif, Helm", + "type": "armour", + "_id": "Z4NTsrX63JNjjZ8Z", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 440, + "copper": null + }, + "protection": 3, + "location": [ + "head" + ], + "equipped": false, + "weight": "heavy", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994438779, + "modifiedTime": 1759994448846, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!Z4NTsrX63JNjjZ8Z" +} diff --git a/packs/protection/_source/Shields_RXPJBkzVxFnoT3Tm.json b/packs/protection/_source/Shields_RXPJBkzVxFnoT3Tm.json new file mode 100644 index 0000000..f561577 --- /dev/null +++ b/packs/protection/_source/Shields_RXPJBkzVxFnoT3Tm.json @@ -0,0 +1,23 @@ +{ + "type": "Item", + "folder": null, + "name": "Shields", + "color": "#04262a", + "sorting": "m", + "_id": "RXPJBkzVxFnoT3Tm", + "description": "", + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994538745, + "modifiedTime": 1759994538745, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!folders!RXPJBkzVxFnoT3Tm" +} diff --git a/packs/weapons/_source/Ammo_gvNPXXRBx2eGIzcU.json b/packs/weapons/_source/Ammo_gvNPXXRBx2eGIzcU.json new file mode 100644 index 0000000..f25006d --- /dev/null +++ b/packs/weapons/_source/Ammo_gvNPXXRBx2eGIzcU.json @@ -0,0 +1,23 @@ +{ + "type": "Item", + "folder": null, + "name": "Ammo", + "color": "#04262a", + "sorting": "a", + "_id": "gvNPXXRBx2eGIzcU", + "description": "", + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993925940, + "modifiedTime": 1759993925940, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!folders!gvNPXXRBx2eGIzcU" +} diff --git a/packs/weapons/_source/Arming_Sword_xXUItaoHTQ2QiaX4.json b/packs/weapons/_source/Arming_Sword_xXUItaoHTQ2QiaX4.json new file mode 100644 index 0000000..07dc4b5 --- /dev/null +++ b/packs/weapons/_source/Arming_Sword_xXUItaoHTQ2QiaX4.json @@ -0,0 +1,47 @@ +{ + "folder": "dBAI76CApXH8qqjx", + "name": "Arming Sword", + "type": "weapon", + "_id": "xXUItaoHTQ2QiaX4", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 80, + "copper": null + }, + "traits": [], + "range": { + "short": null, + "long": null + }, + "damage": 2, + "wear": { + "value": 4, + "max": 4 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759992689272, + "modifiedTime": 1759992708712, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!xXUItaoHTQ2QiaX4" +} diff --git a/packs/weapons/_source/Arrow_gN9JbmouUI7eOrSj.json b/packs/weapons/_source/Arrow_gN9JbmouUI7eOrSj.json new file mode 100644 index 0000000..5538980 --- /dev/null +++ b/packs/weapons/_source/Arrow_gN9JbmouUI7eOrSj.json @@ -0,0 +1,35 @@ +{ + "folder": "gvNPXXRBx2eGIzcU", + "name": "Arrow", + "type": "ammo", + "_id": "gN9JbmouUI7eOrSj", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 12, + "cost": { + "gold": null, + "silver": 3, + "copper": null + }, + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993937035, + "modifiedTime": 1759993944077, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!gN9JbmouUI7eOrSj" +} diff --git a/packs/weapons/_source/Axe__Hammer__Pick_cr35WzuPGDojuOuJ.json b/packs/weapons/_source/Axe__Hammer__Pick_cr35WzuPGDojuOuJ.json new file mode 100644 index 0000000..b36ef0b --- /dev/null +++ b/packs/weapons/_source/Axe__Hammer__Pick_cr35WzuPGDojuOuJ.json @@ -0,0 +1,49 @@ +{ + "folder": "mmd8siMKSLyOeILo", + "name": "Axe, Hammer, Pick", + "type": "weapon", + "_id": "cr35WzuPGDojuOuJ", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 10, + "copper": null + }, + "traits": [ + "Thrown" + ], + "range": { + "short": null, + "long": null + }, + "damage": 0, + "wear": { + "value": 2, + "max": 2 + }, + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759991980652, + "modifiedTime": 1759992328546, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!cr35WzuPGDojuOuJ" +} diff --git a/packs/weapons/_source/Battleaxe__Warhammer_otIFI9TIDPWnT3cq.json b/packs/weapons/_source/Battleaxe__Warhammer_otIFI9TIDPWnT3cq.json new file mode 100644 index 0000000..d4249cb --- /dev/null +++ b/packs/weapons/_source/Battleaxe__Warhammer_otIFI9TIDPWnT3cq.json @@ -0,0 +1,47 @@ +{ + "folder": "dBAI76CApXH8qqjx", + "name": "Battleaxe, Warhammer", + "type": "weapon", + "_id": "otIFI9TIDPWnT3cq", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 40, + "copper": null + }, + "traits": [], + "range": { + "short": null, + "long": null + }, + "damage": 3, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759992730036, + "modifiedTime": 1759992748112, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!otIFI9TIDPWnT3cq" +} diff --git a/packs/weapons/_source/Black_Powder_c86ht86Z9vOEBtNH.json b/packs/weapons/_source/Black_Powder_c86ht86Z9vOEBtNH.json new file mode 100644 index 0000000..ef90dd2 --- /dev/null +++ b/packs/weapons/_source/Black_Powder_c86ht86Z9vOEBtNH.json @@ -0,0 +1,35 @@ +{ + "folder": "gvNPXXRBx2eGIzcU", + "name": "Black Powder", + "type": "ammo", + "_id": "c86ht86Z9vOEBtNH", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 12, + "cost": { + "gold": null, + "silver": 40, + "copper": null + }, + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994005587, + "modifiedTime": 1759994010244, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!c86ht86Z9vOEBtNH" +} diff --git a/packs/weapons/_source/Blowgun_Darts_FvtiEaQhJumPsCwb.json b/packs/weapons/_source/Blowgun_Darts_FvtiEaQhJumPsCwb.json new file mode 100644 index 0000000..9c307f4 --- /dev/null +++ b/packs/weapons/_source/Blowgun_Darts_FvtiEaQhJumPsCwb.json @@ -0,0 +1,35 @@ +{ + "folder": "gvNPXXRBx2eGIzcU", + "name": "Blowgun Darts", + "type": "ammo", + "_id": "FvtiEaQhJumPsCwb", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 12, + "cost": { + "gold": null, + "silver": 2, + "copper": null + }, + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993963869, + "modifiedTime": 1759993969644, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!FvtiEaQhJumPsCwb" +} diff --git a/packs/weapons/_source/Blowgun__Sling_VrG2xer1quhjwUag.json b/packs/weapons/_source/Blowgun__Sling_VrG2xer1quhjwUag.json new file mode 100644 index 0000000..2394a78 --- /dev/null +++ b/packs/weapons/_source/Blowgun__Sling_VrG2xer1quhjwUag.json @@ -0,0 +1,49 @@ +{ + "folder": "vPyj2cK1j66Zyrul", + "name": "Blowgun, Sling", + "type": "weapon", + "_id": "VrG2xer1quhjwUag", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 10, + "copper": null + }, + "traits": [ + "Ammo" + ], + "range": { + "short": 5, + "long": 10 + }, + "damage": 1, + "wear": { + "value": 1, + "max": 1 + }, + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993449825, + "modifiedTime": 1759993468278, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!VrG2xer1quhjwUag" +} diff --git a/packs/weapons/_source/Broadsword_I9QaJTU6O2E9WzUS.json b/packs/weapons/_source/Broadsword_I9QaJTU6O2E9WzUS.json new file mode 100644 index 0000000..7802c4f --- /dev/null +++ b/packs/weapons/_source/Broadsword_I9QaJTU6O2E9WzUS.json @@ -0,0 +1,47 @@ +{ + "folder": "dBAI76CApXH8qqjx", + "name": "Broadsword", + "type": "weapon", + "_id": "I9QaJTU6O2E9WzUS", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 100, + "copper": null + }, + "traits": [], + "range": { + "short": null, + "long": null + }, + "damage": 3, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759992797603, + "modifiedTime": 1759992815028, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!I9QaJTU6O2E9WzUS" +} diff --git a/packs/weapons/_source/Club_NlDJVbXeXRfoCZWp.json b/packs/weapons/_source/Club_NlDJVbXeXRfoCZWp.json new file mode 100644 index 0000000..b174c2b --- /dev/null +++ b/packs/weapons/_source/Club_NlDJVbXeXRfoCZWp.json @@ -0,0 +1,47 @@ +{ + "folder": "mmd8siMKSLyOeILo", + "name": "Club", + "type": "weapon", + "_id": "NlDJVbXeXRfoCZWp", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 2, + "copper": null + }, + "traits": [], + "range": { + "short": null, + "long": null + }, + "damage": 1, + "wear": { + "value": 2, + "max": 2 + }, + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759992392474, + "modifiedTime": 1759992619109, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!NlDJVbXeXRfoCZWp" +} diff --git a/packs/weapons/_source/Crossbow_BNoYUrlpDk6oBeJt.json b/packs/weapons/_source/Crossbow_BNoYUrlpDk6oBeJt.json new file mode 100644 index 0000000..d03ae6d --- /dev/null +++ b/packs/weapons/_source/Crossbow_BNoYUrlpDk6oBeJt.json @@ -0,0 +1,49 @@ +{ + "folder": "8NNF9jBjpmPpmw1B", + "name": "Crossbow", + "type": "weapon", + "_id": "BNoYUrlpDk6oBeJt", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 90, + "copper": null + }, + "traits": [ + "Reload" + ], + "range": { + "short": 10, + "long": 25 + }, + "damage": 3, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993621847, + "modifiedTime": 1759993694978, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!BNoYUrlpDk6oBeJt" +} diff --git a/packs/weapons/_source/Crossbow_Bolts_7cmLLV6o2pPAyyAg.json b/packs/weapons/_source/Crossbow_Bolts_7cmLLV6o2pPAyyAg.json new file mode 100644 index 0000000..1dea670 --- /dev/null +++ b/packs/weapons/_source/Crossbow_Bolts_7cmLLV6o2pPAyyAg.json @@ -0,0 +1,35 @@ +{ + "folder": "gvNPXXRBx2eGIzcU", + "name": "Crossbow Bolts", + "type": "ammo", + "_id": "7cmLLV6o2pPAyyAg", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 12, + "cost": { + "gold": null, + "silver": 3, + "copper": null + }, + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993977460, + "modifiedTime": 1759993982911, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!7cmLLV6o2pPAyyAg" +} diff --git a/packs/weapons/_source/Cutlass__Saber__Scimitar_kSWrbdKdYIRxkWka.json b/packs/weapons/_source/Cutlass__Saber__Scimitar_kSWrbdKdYIRxkWka.json new file mode 100644 index 0000000..d391acc --- /dev/null +++ b/packs/weapons/_source/Cutlass__Saber__Scimitar_kSWrbdKdYIRxkWka.json @@ -0,0 +1,49 @@ +{ + "folder": "dBAI76CApXH8qqjx", + "name": "Cutlass, Saber, Scimitar", + "type": "weapon", + "_id": "kSWrbdKdYIRxkWka", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 120, + "copper": null + }, + "traits": [ + "Agile" + ], + "range": { + "short": null, + "long": null + }, + "damage": 2, + "wear": { + "value": 2, + "max": 2 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759992861725, + "modifiedTime": 1759992882913, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!kSWrbdKdYIRxkWka" +} diff --git a/packs/weapons/_source/Dagger_q8z2HptFaPmeHU9n.json b/packs/weapons/_source/Dagger_q8z2HptFaPmeHU9n.json new file mode 100644 index 0000000..8ded77a --- /dev/null +++ b/packs/weapons/_source/Dagger_q8z2HptFaPmeHU9n.json @@ -0,0 +1,50 @@ +{ + "folder": "mmd8siMKSLyOeILo", + "name": "Dagger", + "type": "weapon", + "_id": "q8z2HptFaPmeHU9n", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 20, + "copper": null + }, + "traits": [ + "Agile", + "Thrown" + ], + "range": { + "short": null, + "long": null + }, + "damage": 1, + "wear": { + "value": 1, + "max": 1 + }, + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759992606052, + "modifiedTime": 1759992639628, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!q8z2HptFaPmeHU9n" +} diff --git a/packs/weapons/_source/Darts_rDxS6EJzg2zvSpxR.json b/packs/weapons/_source/Darts_rDxS6EJzg2zvSpxR.json new file mode 100644 index 0000000..6caf1c7 --- /dev/null +++ b/packs/weapons/_source/Darts_rDxS6EJzg2zvSpxR.json @@ -0,0 +1,49 @@ +{ + "folder": "vPyj2cK1j66Zyrul", + "name": "Darts", + "type": "weapon", + "_id": "rDxS6EJzg2zvSpxR", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 6, + "cost": { + "gold": null, + "silver": 30, + "copper": null + }, + "traits": [ + "Thrown" + ], + "range": { + "short": 3, + "long": 6 + }, + "damage": 1, + "wear": { + "value": 1, + "max": 1 + }, + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993477954, + "modifiedTime": 1759993498878, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!rDxS6EJzg2zvSpxR" +} diff --git a/packs/weapons/_source/Flintlock_Pistol_1vxM6KoEPrQ7pjcg.json b/packs/weapons/_source/Flintlock_Pistol_1vxM6KoEPrQ7pjcg.json new file mode 100644 index 0000000..868057d --- /dev/null +++ b/packs/weapons/_source/Flintlock_Pistol_1vxM6KoEPrQ7pjcg.json @@ -0,0 +1,50 @@ +{ + "folder": "vPyj2cK1j66Zyrul", + "name": "Flintlock Pistol", + "type": "weapon", + "_id": "1vxM6KoEPrQ7pjcg", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 260, + "copper": null + }, + "traits": [ + "Reload", + "Loud" + ], + "range": { + "short": 5, + "long": 10 + }, + "damage": 2, + "wear": { + "value": 2, + "max": 2 + }, + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993514814, + "modifiedTime": 1759993538727, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!1vxM6KoEPrQ7pjcg" +} diff --git a/packs/weapons/_source/Flintlock_Rifle_xUGUgnjJsKUPgPpX.json b/packs/weapons/_source/Flintlock_Rifle_xUGUgnjJsKUPgPpX.json new file mode 100644 index 0000000..13105fc --- /dev/null +++ b/packs/weapons/_source/Flintlock_Rifle_xUGUgnjJsKUPgPpX.json @@ -0,0 +1,50 @@ +{ + "folder": "IkSGLBUzPI9Jbcj7", + "name": "Flintlock Rifle", + "type": "weapon", + "_id": "xUGUgnjJsKUPgPpX", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 640, + "copper": null + }, + "traits": [ + "Reload", + "Loud" + ], + "range": { + "short": 15, + "long": 30 + }, + "damage": 4, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "heavy", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993769479, + "modifiedTime": 1759993794528, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!xUGUgnjJsKUPgPpX" +} diff --git a/packs/weapons/_source/Great_Arrows_FQ5VBjR0LdXf8Nh2.json b/packs/weapons/_source/Great_Arrows_FQ5VBjR0LdXf8Nh2.json new file mode 100644 index 0000000..6f80b11 --- /dev/null +++ b/packs/weapons/_source/Great_Arrows_FQ5VBjR0LdXf8Nh2.json @@ -0,0 +1,35 @@ +{ + "folder": "gvNPXXRBx2eGIzcU", + "name": "Great Arrows", + "type": "ammo", + "_id": "FQ5VBjR0LdXf8Nh2", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 12, + "cost": { + "gold": null, + "silver": 12, + "copper": null + }, + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993988701, + "modifiedTime": 1759993993428, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!FQ5VBjR0LdXf8Nh2" +} diff --git a/packs/weapons/_source/Greataxe__Maul__Sword_Pfm448hGPVSuyyrd.json b/packs/weapons/_source/Greataxe__Maul__Sword_Pfm448hGPVSuyyrd.json new file mode 100644 index 0000000..ccba1ec --- /dev/null +++ b/packs/weapons/_source/Greataxe__Maul__Sword_Pfm448hGPVSuyyrd.json @@ -0,0 +1,49 @@ +{ + "folder": "3tp9cwpArQNOpkAY", + "name": "Greataxe, Maul, Sword", + "type": "weapon", + "_id": "Pfm448hGPVSuyyrd", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 120, + "copper": null + }, + "traits": [ + "Long" + ], + "range": { + "short": null, + "long": null + }, + "damage": 4, + "wear": { + "value": 4, + "max": 4 + }, + "equipped": false, + "weight": "heavy", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993233713, + "modifiedTime": 1759993258414, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!Pfm448hGPVSuyyrd" +} diff --git a/packs/weapons/_source/Greatbow_N80F8sq9SaHrXBvS.json b/packs/weapons/_source/Greatbow_N80F8sq9SaHrXBvS.json new file mode 100644 index 0000000..a823775 --- /dev/null +++ b/packs/weapons/_source/Greatbow_N80F8sq9SaHrXBvS.json @@ -0,0 +1,49 @@ +{ + "folder": "IkSGLBUzPI9Jbcj7", + "name": "Greatbow", + "type": "weapon", + "_id": "N80F8sq9SaHrXBvS", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 320, + "copper": null + }, + "traits": [ + "Ammo" + ], + "range": { + "short": 20, + "long": 40 + }, + "damage": 4, + "wear": { + "value": 4, + "max": 4 + }, + "equipped": false, + "weight": "heavy", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993806102, + "modifiedTime": 1759993839512, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!N80F8sq9SaHrXBvS" +} diff --git a/packs/weapons/_source/Greatclub__Staff_Ct9iNF9KPMGStSQo.json b/packs/weapons/_source/Greatclub__Staff_Ct9iNF9KPMGStSQo.json new file mode 100644 index 0000000..181532c --- /dev/null +++ b/packs/weapons/_source/Greatclub__Staff_Ct9iNF9KPMGStSQo.json @@ -0,0 +1,49 @@ +{ + "folder": "3tp9cwpArQNOpkAY", + "name": "Greatclub, Staff", + "type": "weapon", + "_id": "Ct9iNF9KPMGStSQo", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 30, + "copper": null + }, + "traits": [ + "Long" + ], + "range": { + "short": null, + "long": null + }, + "damage": 4, + "wear": { + "value": 4, + "max": 4 + }, + "equipped": false, + "weight": "heavy", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993276032, + "modifiedTime": 1759993292511, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!Ct9iNF9KPMGStSQo" +} diff --git a/packs/weapons/_source/Hand_Crossbow_5sUeNom6dn6MaoAE.json b/packs/weapons/_source/Hand_Crossbow_5sUeNom6dn6MaoAE.json new file mode 100644 index 0000000..0dc3807 --- /dev/null +++ b/packs/weapons/_source/Hand_Crossbow_5sUeNom6dn6MaoAE.json @@ -0,0 +1,49 @@ +{ + "folder": "vPyj2cK1j66Zyrul", + "name": "Hand Crossbow", + "type": "weapon", + "_id": "5sUeNom6dn6MaoAE", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 120, + "copper": null + }, + "traits": [ + "Reload" + ], + "range": { + "short": 5, + "long": 10 + }, + "damage": 2, + "wear": { + "value": 1, + "max": 1 + }, + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993551322, + "modifiedTime": 1759993570977, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!5sUeNom6dn6MaoAE" +} diff --git a/packs/weapons/_source/Hand_Weapons_3mr6aZe43z7YBysA.json b/packs/weapons/_source/Hand_Weapons_3mr6aZe43z7YBysA.json new file mode 100644 index 0000000..cc22c9f --- /dev/null +++ b/packs/weapons/_source/Hand_Weapons_3mr6aZe43z7YBysA.json @@ -0,0 +1,23 @@ +{ + "type": "Item", + "folder": null, + "name": "Hand Weapons", + "color": "#04262a", + "sorting": "m", + "_id": "3mr6aZe43z7YBysA", + "description": "", + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759992349332, + "modifiedTime": 1759993205214, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!folders!3mr6aZe43z7YBysA" +} diff --git a/packs/weapons/_source/Heavy_3tp9cwpArQNOpkAY.json b/packs/weapons/_source/Heavy_3tp9cwpArQNOpkAY.json new file mode 100644 index 0000000..729d6f9 --- /dev/null +++ b/packs/weapons/_source/Heavy_3tp9cwpArQNOpkAY.json @@ -0,0 +1,21 @@ +{ + "type": "Item", + "folder": "3mr6aZe43z7YBysA", + "name": "Heavy", + "color": "#06393f", + "sorting": "a", + "_id": "3tp9cwpArQNOpkAY", + "description": "", + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "lastModifiedBy": null + }, + "_key": "!folders!3tp9cwpArQNOpkAY" +} diff --git a/packs/weapons/_source/Heavy_Crossbow_xJzHTrYsJVL2WsSF.json b/packs/weapons/_source/Heavy_Crossbow_xJzHTrYsJVL2WsSF.json new file mode 100644 index 0000000..bd06196 --- /dev/null +++ b/packs/weapons/_source/Heavy_Crossbow_xJzHTrYsJVL2WsSF.json @@ -0,0 +1,49 @@ +{ + "folder": "IkSGLBUzPI9Jbcj7", + "name": "Heavy Crossbow", + "type": "weapon", + "_id": "xJzHTrYsJVL2WsSF", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 200, + "copper": null + }, + "traits": [ + "Ammo" + ], + "range": { + "short": 20, + "long": 40 + }, + "damage": 4, + "wear": { + "value": 4, + "max": 4 + }, + "equipped": false, + "weight": "heavy", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993848517, + "modifiedTime": 1759993869078, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!xJzHTrYsJVL2WsSF" +} diff --git a/packs/weapons/_source/Heavy_IkSGLBUzPI9Jbcj7.json b/packs/weapons/_source/Heavy_IkSGLBUzPI9Jbcj7.json new file mode 100644 index 0000000..b7585e5 --- /dev/null +++ b/packs/weapons/_source/Heavy_IkSGLBUzPI9Jbcj7.json @@ -0,0 +1,21 @@ +{ + "type": "Item", + "folder": "sjc6X9bKf7BY04Ar", + "name": "Heavy", + "color": "#06393f", + "sorting": "a", + "_id": "IkSGLBUzPI9Jbcj7", + "description": "", + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "lastModifiedBy": null + }, + "_key": "!folders!IkSGLBUzPI9Jbcj7" +} diff --git a/packs/weapons/_source/Knife_fv5D0xOJVpOwnyTn.json b/packs/weapons/_source/Knife_fv5D0xOJVpOwnyTn.json new file mode 100644 index 0000000..04d325c --- /dev/null +++ b/packs/weapons/_source/Knife_fv5D0xOJVpOwnyTn.json @@ -0,0 +1,49 @@ +{ + "folder": "mmd8siMKSLyOeILo", + "name": "Knife", + "type": "weapon", + "_id": "fv5D0xOJVpOwnyTn", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 6, + "copper": null + }, + "traits": [ + "Thrown" + ], + "range": { + "short": null, + "long": null + }, + "damage": 1, + "wear": { + "value": 1, + "max": 1 + }, + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759992653763, + "modifiedTime": 1759992669428, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!fv5D0xOJVpOwnyTn" +} diff --git a/packs/weapons/_source/Light_mmd8siMKSLyOeILo.json b/packs/weapons/_source/Light_mmd8siMKSLyOeILo.json new file mode 100644 index 0000000..f243f42 --- /dev/null +++ b/packs/weapons/_source/Light_mmd8siMKSLyOeILo.json @@ -0,0 +1,23 @@ +{ + "type": "Item", + "folder": "3mr6aZe43z7YBysA", + "name": "Light", + "color": "#06393f", + "sorting": "a", + "_id": "mmd8siMKSLyOeILo", + "description": "", + "sort": -100000, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759991969340, + "modifiedTime": 1759993210807, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!folders!mmd8siMKSLyOeILo" +} diff --git a/packs/weapons/_source/Light_vPyj2cK1j66Zyrul.json b/packs/weapons/_source/Light_vPyj2cK1j66Zyrul.json new file mode 100644 index 0000000..fb4cbf3 --- /dev/null +++ b/packs/weapons/_source/Light_vPyj2cK1j66Zyrul.json @@ -0,0 +1,21 @@ +{ + "type": "Item", + "folder": "sjc6X9bKf7BY04Ar", + "name": "Light", + "color": "#06393f", + "sorting": "a", + "_id": "vPyj2cK1j66Zyrul", + "description": "", + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "lastModifiedBy": null + }, + "_key": "!folders!vPyj2cK1j66Zyrul" +} diff --git a/packs/weapons/_source/Long_Rifle_dn1eja68NNuxB8K1.json b/packs/weapons/_source/Long_Rifle_dn1eja68NNuxB8K1.json new file mode 100644 index 0000000..d20d8c3 --- /dev/null +++ b/packs/weapons/_source/Long_Rifle_dn1eja68NNuxB8K1.json @@ -0,0 +1,50 @@ +{ + "folder": "IkSGLBUzPI9Jbcj7", + "name": "Long Rifle", + "type": "weapon", + "_id": "dn1eja68NNuxB8K1", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 840, + "copper": null + }, + "traits": [ + "Reload", + "Loud" + ], + "range": { + "short": 20, + "long": 40 + }, + "damage": 4, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "heavy", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993878663, + "modifiedTime": 1759993902478, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!dn1eja68NNuxB8K1" +} diff --git a/packs/weapons/_source/Longbow_oyVNU8XgMiZI0Uxr.json b/packs/weapons/_source/Longbow_oyVNU8XgMiZI0Uxr.json new file mode 100644 index 0000000..57ee032 --- /dev/null +++ b/packs/weapons/_source/Longbow_oyVNU8XgMiZI0Uxr.json @@ -0,0 +1,49 @@ +{ + "folder": "8NNF9jBjpmPpmw1B", + "name": "Longbow", + "type": "weapon", + "_id": "oyVNU8XgMiZI0Uxr", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 80, + "copper": null + }, + "traits": [ + "Ammo" + ], + "range": { + "short": 9, + "long": 30 + }, + "damage": 3, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993703627, + "modifiedTime": 1759993727378, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!oyVNU8XgMiZI0Uxr" +} diff --git a/packs/weapons/_source/Longsword_7ezV0MrGA0duoGbl.json b/packs/weapons/_source/Longsword_7ezV0MrGA0duoGbl.json new file mode 100644 index 0000000..7ca740d --- /dev/null +++ b/packs/weapons/_source/Longsword_7ezV0MrGA0duoGbl.json @@ -0,0 +1,49 @@ +{ + "folder": "dBAI76CApXH8qqjx", + "name": "Longsword", + "type": "weapon", + "_id": "7ezV0MrGA0duoGbl", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 220, + "copper": null + }, + "traits": [ + "Able" + ], + "range": { + "short": null, + "long": null + }, + "damage": 3, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759992894140, + "modifiedTime": 1759992913378, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!7ezV0MrGA0duoGbl" +} diff --git a/packs/weapons/_source/Modest_8NNF9jBjpmPpmw1B.json b/packs/weapons/_source/Modest_8NNF9jBjpmPpmw1B.json new file mode 100644 index 0000000..ca9314d --- /dev/null +++ b/packs/weapons/_source/Modest_8NNF9jBjpmPpmw1B.json @@ -0,0 +1,21 @@ +{ + "type": "Item", + "folder": "sjc6X9bKf7BY04Ar", + "name": "Modest", + "color": "#06393f", + "sorting": "a", + "_id": "8NNF9jBjpmPpmw1B", + "description": "", + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "lastModifiedBy": null + }, + "_key": "!folders!8NNF9jBjpmPpmw1B" +} diff --git a/packs/weapons/_source/Modest_dBAI76CApXH8qqjx.json b/packs/weapons/_source/Modest_dBAI76CApXH8qqjx.json new file mode 100644 index 0000000..0828e40 --- /dev/null +++ b/packs/weapons/_source/Modest_dBAI76CApXH8qqjx.json @@ -0,0 +1,21 @@ +{ + "type": "Item", + "folder": "3mr6aZe43z7YBysA", + "name": "Modest", + "color": "#06393f", + "sorting": "a", + "_id": "dBAI76CApXH8qqjx", + "description": "", + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "lastModifiedBy": null + }, + "_key": "!folders!dBAI76CApXH8qqjx" +} diff --git a/packs/weapons/_source/Poleaxe__Glaive__Halberd_j6C9IyebpKsk7M6R.json b/packs/weapons/_source/Poleaxe__Glaive__Halberd_j6C9IyebpKsk7M6R.json new file mode 100644 index 0000000..28cf30c --- /dev/null +++ b/packs/weapons/_source/Poleaxe__Glaive__Halberd_j6C9IyebpKsk7M6R.json @@ -0,0 +1,49 @@ +{ + "folder": "3tp9cwpArQNOpkAY", + "name": "Poleaxe, Glaive, Halberd", + "type": "weapon", + "_id": "j6C9IyebpKsk7M6R", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 60, + "copper": null + }, + "traits": [ + "Long" + ], + "range": { + "short": null, + "long": null + }, + "damage": 4, + "wear": { + "value": 4, + "max": 4 + }, + "equipped": false, + "weight": "heavy", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993308439, + "modifiedTime": 1759993324411, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!j6C9IyebpKsk7M6R" +} diff --git a/packs/weapons/_source/Quarterstaff_0ebCxTylmQa5UJvF.json b/packs/weapons/_source/Quarterstaff_0ebCxTylmQa5UJvF.json new file mode 100644 index 0000000..63aaffe --- /dev/null +++ b/packs/weapons/_source/Quarterstaff_0ebCxTylmQa5UJvF.json @@ -0,0 +1,49 @@ +{ + "folder": "dBAI76CApXH8qqjx", + "name": "Quarterstaff", + "type": "weapon", + "_id": "0ebCxTylmQa5UJvF", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 20, + "copper": null + }, + "traits": [ + "Able" + ], + "range": { + "short": null, + "long": null + }, + "damage": 2, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759992932299, + "modifiedTime": 1759992950112, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!0ebCxTylmQa5UJvF" +} diff --git a/packs/weapons/_source/Ranged_Weapons_sjc6X9bKf7BY04Ar.json b/packs/weapons/_source/Ranged_Weapons_sjc6X9bKf7BY04Ar.json new file mode 100644 index 0000000..ff8a606 --- /dev/null +++ b/packs/weapons/_source/Ranged_Weapons_sjc6X9bKf7BY04Ar.json @@ -0,0 +1,23 @@ +{ + "type": "Item", + "folder": null, + "name": "Ranged Weapons", + "color": "#04262a", + "sorting": "m", + "_id": "sjc6X9bKf7BY04Ar", + "description": "", + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993402367, + "modifiedTime": 1759993402367, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!folders!sjc6X9bKf7BY04Ar" +} diff --git a/packs/weapons/_source/Rapier__Foil_cgEQKXKnSShCRQaq.json b/packs/weapons/_source/Rapier__Foil_cgEQKXKnSShCRQaq.json new file mode 100644 index 0000000..b2a5f0c --- /dev/null +++ b/packs/weapons/_source/Rapier__Foil_cgEQKXKnSShCRQaq.json @@ -0,0 +1,50 @@ +{ + "folder": "dBAI76CApXH8qqjx", + "name": "Rapier, Foil", + "type": "weapon", + "_id": "cgEQKXKnSShCRQaq", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 120, + "copper": null + }, + "traits": [ + "Agile", + "Long" + ], + "range": { + "short": null, + "long": null + }, + "damage": 2, + "wear": { + "value": 2, + "max": 2 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759992972763, + "modifiedTime": 1759992992895, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!cgEQKXKnSShCRQaq" +} diff --git a/packs/weapons/_source/Scythe_PnBWkLNzmQjXbB94.json b/packs/weapons/_source/Scythe_PnBWkLNzmQjXbB94.json new file mode 100644 index 0000000..e999370 --- /dev/null +++ b/packs/weapons/_source/Scythe_PnBWkLNzmQjXbB94.json @@ -0,0 +1,49 @@ +{ + "folder": "3tp9cwpArQNOpkAY", + "name": "Scythe", + "type": "weapon", + "_id": "PnBWkLNzmQjXbB94", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 80, + "copper": null + }, + "traits": [ + "Long" + ], + "range": { + "short": null, + "long": null + }, + "damage": 4, + "wear": { + "value": 4, + "max": 4 + }, + "equipped": false, + "weight": "heavy", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993335901, + "modifiedTime": 1759993351161, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!PnBWkLNzmQjXbB94" +} diff --git a/packs/weapons/_source/Shortbow_qmnDO3TrKoeW7DZB.json b/packs/weapons/_source/Shortbow_qmnDO3TrKoeW7DZB.json new file mode 100644 index 0000000..484b4ab --- /dev/null +++ b/packs/weapons/_source/Shortbow_qmnDO3TrKoeW7DZB.json @@ -0,0 +1,49 @@ +{ + "folder": "8NNF9jBjpmPpmw1B", + "name": "Shortbow", + "type": "weapon", + "_id": "qmnDO3TrKoeW7DZB", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 50, + "copper": null + }, + "traits": [ + "Ammo" + ], + "range": { + "short": 6, + "long": 20 + }, + "damage": 2, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993734661, + "modifiedTime": 1759993756094, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!qmnDO3TrKoeW7DZB" +} diff --git a/packs/weapons/_source/Shortsword_UulalWrMRtSX5KxZ.json b/packs/weapons/_source/Shortsword_UulalWrMRtSX5KxZ.json new file mode 100644 index 0000000..06322d5 --- /dev/null +++ b/packs/weapons/_source/Shortsword_UulalWrMRtSX5KxZ.json @@ -0,0 +1,47 @@ +{ + "folder": "dBAI76CApXH8qqjx", + "name": "Shortsword", + "type": "weapon", + "_id": "UulalWrMRtSX5KxZ", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 60, + "copper": null + }, + "traits": [], + "range": { + "short": null, + "long": null + }, + "damage": 2, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993008835, + "modifiedTime": 1759993028879, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!UulalWrMRtSX5KxZ" +} diff --git a/packs/weapons/_source/Shot_Q5i7hMOPgb9oXmh5.json b/packs/weapons/_source/Shot_Q5i7hMOPgb9oXmh5.json new file mode 100644 index 0000000..5338692 --- /dev/null +++ b/packs/weapons/_source/Shot_Q5i7hMOPgb9oXmh5.json @@ -0,0 +1,35 @@ +{ + "folder": "gvNPXXRBx2eGIzcU", + "name": "Shot", + "type": "ammo", + "_id": "Q5i7hMOPgb9oXmh5", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 12, + "cost": { + "gold": null, + "silver": 10, + "copper": null + }, + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759994014714, + "modifiedTime": 1759994020511, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!Q5i7hMOPgb9oXmh5" +} diff --git a/packs/weapons/_source/Sickle_o9saXoHahbxTxt4h.json b/packs/weapons/_source/Sickle_o9saXoHahbxTxt4h.json new file mode 100644 index 0000000..f0c8fe8 --- /dev/null +++ b/packs/weapons/_source/Sickle_o9saXoHahbxTxt4h.json @@ -0,0 +1,47 @@ +{ + "folder": "dBAI76CApXH8qqjx", + "name": "Sickle", + "type": "weapon", + "_id": "o9saXoHahbxTxt4h", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 80, + "copper": null + }, + "traits": [], + "range": { + "short": null, + "long": null + }, + "damage": 3, + "wear": { + "value": 2, + "max": 2 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993051839, + "modifiedTime": 1759993069744, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!o9saXoHahbxTxt4h" +} diff --git a/packs/weapons/_source/Spear__Javelin__Pike_bTOoWxHeLSY9JWNY.json b/packs/weapons/_source/Spear__Javelin__Pike_bTOoWxHeLSY9JWNY.json new file mode 100644 index 0000000..477bc8b --- /dev/null +++ b/packs/weapons/_source/Spear__Javelin__Pike_bTOoWxHeLSY9JWNY.json @@ -0,0 +1,50 @@ +{ + "folder": "dBAI76CApXH8qqjx", + "name": "Spear, Javelin, Pike", + "type": "weapon", + "_id": "bTOoWxHeLSY9JWNY", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 30, + "copper": null + }, + "traits": [ + "Agile", + "Thrown" + ], + "range": { + "short": 5, + "long": 10 + }, + "damage": 2, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993081111, + "modifiedTime": 1759993110561, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!bTOoWxHeLSY9JWNY" +} diff --git a/packs/weapons/_source/Throwing_Axe_n2j1gxnn3WnUPag6.json b/packs/weapons/_source/Throwing_Axe_n2j1gxnn3WnUPag6.json new file mode 100644 index 0000000..b193d2a --- /dev/null +++ b/packs/weapons/_source/Throwing_Axe_n2j1gxnn3WnUPag6.json @@ -0,0 +1,49 @@ +{ + "folder": "vPyj2cK1j66Zyrul", + "name": "Throwing Axe", + "type": "weapon", + "_id": "n2j1gxnn3WnUPag6", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 30, + "copper": null + }, + "traits": [ + "Thrown" + ], + "range": { + "short": 2, + "long": 4 + }, + "damage": 1, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "light", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993592390, + "modifiedTime": 1759993609878, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!n2j1gxnn3WnUPag6" +} diff --git a/packs/weapons/_source/Warclub__Flail__Mace_WMiQdSVgM8z84MEv.json b/packs/weapons/_source/Warclub__Flail__Mace_WMiQdSVgM8z84MEv.json new file mode 100644 index 0000000..0f102f8 --- /dev/null +++ b/packs/weapons/_source/Warclub__Flail__Mace_WMiQdSVgM8z84MEv.json @@ -0,0 +1,47 @@ +{ + "folder": "dBAI76CApXH8qqjx", + "name": "Warclub, Flail, Mace", + "type": "weapon", + "_id": "WMiQdSVgM8z84MEv", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 80, + "copper": null + }, + "traits": [], + "range": { + "short": null, + "long": null + }, + "damage": 2, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993125576, + "modifiedTime": 1759993138211, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!WMiQdSVgM8z84MEv" +} diff --git a/packs/weapons/_source/Whip_vVF6LZSFi0pNB95E.json b/packs/weapons/_source/Whip_vVF6LZSFi0pNB95E.json new file mode 100644 index 0000000..7380fb8 --- /dev/null +++ b/packs/weapons/_source/Whip_vVF6LZSFi0pNB95E.json @@ -0,0 +1,50 @@ +{ + "folder": "dBAI76CApXH8qqjx", + "name": "Whip", + "type": "weapon", + "_id": "vVF6LZSFi0pNB95E", + "img": "icons/svg/item-bag.svg", + "system": { + "quantity": 1, + "cost": { + "gold": null, + "silver": 20, + "copper": null + }, + "traits": [ + "Agile", + "Long" + ], + "range": { + "short": null, + "long": null + }, + "damage": 1, + "wear": { + "value": 3, + "max": 3 + }, + "equipped": false, + "weight": "modest", + "access": "" + }, + "effects": [], + "sort": 0, + "ownership": { + "default": 0, + "9x9FgB0YTeCJJUDK": 3 + }, + "flags": {}, + "_stats": { + "compendiumSource": null, + "duplicateSource": null, + "exportSource": null, + "coreVersion": "13.350", + "systemId": "ripcrypt", + "systemVersion": "0.2.0", + "createdTime": 1759993155738, + "modifiedTime": 1759993176128, + "lastModifiedBy": "9x9FgB0YTeCJJUDK" + }, + "_key": "!items!vVF6LZSFi0pNB95E" +} diff --git a/scripts/buildCompendia.mjs b/scripts/buildCompendia.mjs new file mode 100644 index 0000000..88ab4e4 --- /dev/null +++ b/scripts/buildCompendia.mjs @@ -0,0 +1,36 @@ +import { existsSync } from "fs"; +import { readFile } from "fs/promises"; +import { join } from "path"; +import { compilePack } from "@foundryvtt/foundryvtt-cli"; +import { pathToFileURL } from "url"; + +export async function buildCompendia() { + const manifest = JSON.parse(await readFile(`./system.json`, `utf-8`)); + + if (!manifest.packs || manifest.packs.length === 0) { + console.log(`No compendium packs defined`); + process.exit(0); + }; + console.log(`Packing compendia`); + + for (const compendium of manifest.packs) { + console.debug(`Packing ${compendium.label} (${compendium.name})`); + let src = join(process.cwd(), compendium.path, `_source`); + if (!existsSync(src)) { + console.warn(`${compendium.path} doesn't exist, skipping.`) + continue; + }; + await compilePack( + src, + join(process.cwd(), compendium.path), + { recursive: true }, + ); + console.debug(`Finished packing compendium: ${compendium.name}`); + }; + + console.log(`Finished packing all compendia`) +}; + +if (import.meta.url === pathToFileURL(process.argv[1]).href) { + buildCompendia(); +}; diff --git a/scripts/extractCompendia.mjs b/scripts/extractCompendia.mjs new file mode 100644 index 0000000..0730b38 --- /dev/null +++ b/scripts/extractCompendia.mjs @@ -0,0 +1,31 @@ +import { readFile } from "fs/promises"; +import { join } from "path"; +import { extractPack } from "@foundryvtt/foundryvtt-cli"; +import { pathToFileURL } from "url"; + +export async function extractCompendia() { + const manifest = JSON.parse(await readFile(`./system.json`, `utf-8`)); + + if (!manifest.packs || manifest.packs.length === 0) { + console.log(`No compendium packs defined`); + process.exit(0); + }; + console.log(`Extracting compendia`); + + for (const compendium of manifest.packs) { + console.debug(`Unpacking ${compendium.label} (${compendium.name})`); + let src = join(process.cwd(), compendium.path, `_source`); + await extractPack( + join(process.cwd(), compendium.path), + src, + { recursive: true }, + ); + console.debug(`Finished unpacking compendium: ${compendium.name}`); + }; + + console.log(`Finished unpacking all compendia`); +}; + +if (import.meta.url === pathToFileURL(process.argv[1]).href) { + extractCompendia(); +}; diff --git a/scripts/linkFoundry.mjs b/scripts/linkFoundry.mjs new file mode 100644 index 0000000..3ee94c5 --- /dev/null +++ b/scripts/linkFoundry.mjs @@ -0,0 +1,47 @@ +import { existsSync } from "fs"; +import { symlink, unlink } from "fs/promises"; +import { join } from "path"; +import { config } from "dotenv"; + +config({ quiet: true }); + +const root = process.env.FOUNDRY_ROOT; + +// Early exit +if (!root) { + console.error(`Must provide a FOUNDRY_ROOT environment variable`); + process.exit(1); +}; + +// Assert Foundry exists +if (!existsSync(root)) { + console.error(`Foundry root not found.`); + process.exit(1); +}; + +// Removing existing symlink +if (existsSync(`foundry`)) { + console.log(`Attempting to unlink foundry instance`); + try { + await unlink(`foundry`); + } catch { + console.error(`Failed to unlink foundry folder.`); + process.exit(1); + }; +}; + +// Account for if the root is pointing at an Electron install +let targetRoot = root; +if (existsSync(join(root, `resources`, `app`))) { + console.log(`Switching to use the "${root}/resources/app" directory`); + targetRoot = join(root, `resources`, `app`); +}; + +// Create symlink +console.log(`Linking foundry source into folder`); +try { + await symlink(targetRoot, `foundry`); +} catch (e) { + console.error(e); + process.exit(1); +}; diff --git a/system.json b/system.json index c946a40..d4b61ed 100644 --- a/system.json +++ b/system.json @@ -2,17 +2,14 @@ "id": "ripcrypt", "title": "RipCrypt", "description": "A dungeon sprint RPG. Faster than an arrow to the eye. Smoother than a clean blade. Compact with consequences.", - "version": "0.1.0", + "version": "0.2.0", "compatibility": { "minimum": 13, - "verified": 13.346, + "verified": "13.350", "maximum": 13 }, "authors": [ - { - "name": "Oliver Akins", - "url": "https://oliver.akins.me" - } + { "name": "Oliver" } ], "esmodules": [ "module/main.mjs" @@ -30,11 +27,12 @@ "path": "langs/en-ca.json" } ], - "url": "https://github.com/Oliver-Akins/Foundry-RipCrypt", - "manifest": "https://github.com/Oliver-Akins/Foundry-RipCrypt/releases/latest/download/module.json", - "download": "https://github.com/Oliver-Akins/Foundry-RipCrypt/releases/latest/download/release.zip", + "url": "https://github.com/Eldritch-Oliver/Foundry-RipCrypt", + "manifest": "https://github.com/Eldritch-Oliver/Foundry-RipCrypt/releases/latest/download/module.json", + "download": "#{DOWNLOAD}#", "readme": "README.md", "bugs": "", + "socket": true, "flags": { "hotReload": { "extensions": ["css", "hbs", "json", "mjs", "svg"], @@ -55,5 +53,74 @@ "skill": {}, "weapon": {} } - } + }, + "packs": [ + { + "name": "protection", + "label": "Armour & Shields", + "system": "ripcrypt", + "path": "packs/protection", + "type": "Item", + "ownership": { + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" + } + }, + { + "name": "weapons", + "label": "Weapons & Ammo", + "system": "ripcrypt", + "path": "packs/weapons", + "type": "Item", + "ownership": { + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" + } + }, + { + "name": "skills", + "label": "Skills", + "system": "ripcrypt", + "path": "packs/skills", + "type": "Item", + "ownership": { + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" + } + }, + { + "name": "geist", + "label": "Geist", + "system": "ripcrypt", + "path": "packs/geist", + "type": "Actor", + "ownership": { + "PLAYER": "NONE", + "ASSISTANT": "OWNER" + } + } + ], + "packFolders": [ + { + "name": "RipCrypt Sprint Start", + "color": "#04262a", + "sorting": "m", + "folders": [ + { + "name": "Character Options", + "color": "#06393f", + "sorting": "m", + "folders": [], + "packs": [ + "protection", + "weapons", + "skills" + ] + } + ], + "packs": [ + "geist" + ] + } + ] } diff --git a/templates/Apps/AllItemSheetV1/content.hbs b/templates/Apps/AllItemSheetV1/content.hbs index 0fb9599..523c483 100644 --- a/templates/Apps/AllItemSheetV1/content.hbs +++ b/templates/Apps/AllItemSheetV1/content.hbs @@ -1,6 +1,6 @@
| {{ rc-i18n "RipCrypt.common.weapon.singular" }} | ++ {{ rc-i18n "RipCrypt.common.weapon.singular" }} + + | {{ rc-i18n "RipCrypt.Apps.traits-range" }} | {{ rc-i18n "RipCrypt.common.wear" }} | {{ rc-i18n "RipCrypt.common.damage" }} | diff --git a/templates/Apps/StatsCardV1/style.css b/templates/Apps/StatsCardV1/style.css index e33246e..13092a8 100644 --- a/templates/Apps/StatsCardV1/style.css +++ b/templates/Apps/StatsCardV1/style.css @@ -12,6 +12,10 @@ color: var(--base-text); .col-header { + display: flex; + flex-direction: row; + gap: 4px; + align-items: center; background: var(--section-header-background); color: var(--section-header-text); } @@ -49,6 +53,13 @@ margin-left: calc(var(--col-gap) * -1); padding-left: var(--col-gap); } + .action-row { + grid-column: span 3; + + button { + border-bottom: 2px dashed var(--accent-3); + } + } .glory-label { grid-column: 2 / span 1; diff --git a/templates/Apps/apps.css b/templates/Apps/apps.css index 30af300..db88f7e 100644 --- a/templates/Apps/apps.css +++ b/templates/Apps/apps.css @@ -6,6 +6,7 @@ @import url("./StatsCardV1/style.css"); @import url("./SkillsCardV1/style.css"); @import url("./RichEditor/style.css"); +@import url("./ArmourSheet/style.css"); @import url("./popover.css"); @import url("./popovers/AmmoTracker/style.css"); diff --git a/templates/Apps/partials/item-header.hbs b/templates/Apps/partials/item-header.hbs new file mode 100644 index 0000000..300c166 --- /dev/null +++ b/templates/Apps/partials/item-header.hbs @@ -0,0 +1,28 @@ +{{!-- +Required parameters: + "name" : the name of the item + "system.quantity" : the quantity of the item + "meta.idp" : the ID Prefix for the application +--}} +
|---|