diff --git a/.env.template b/.env.template deleted file mode 100644 index 180dbd6..0000000 --- a/.env.template +++ /dev/null @@ -1,2 +0,0 @@ -# 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 eecafc4..7763240 100644 --- a/.github/workflows/draft-release.yaml +++ b/.github/workflows/draft-release.yaml @@ -29,22 +29,20 @@ jobs: if: ${{ steps.check-tag.outputs.exists == 'true' }} run: exit 1 - - name: "Building compendia" - run: "npm run data:build" + - name: Ensure there are specific files to release + if: ${{ vars.files_to_release == '' }} + run: exit 1 - - name: "Removing compendium source" - run: "rm -rf packs/**/_source" + - name: Move system.json to a temp file + id: manifest-move + run: mv system.json module.temp.json - - name: Update the manifest with the relevant properties + - name: Update the download property in the manifest id: manifest-update - 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" + 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 - name: Create the zip - run: zip -r release.zip system.json packs module langs assets templates README.md + run: zip -r release.zip ${{ vars.files_to_release }} - name: Create the draft release uses: ncipollo/release-action@v1 @@ -52,6 +50,5 @@ jobs: tag: "v${{ steps.version.outputs.version }}" commit: ${{ github.ref }} draft: true - body: generateReleaseNotes: true artifacts: "release.zip,system.json" \ No newline at end of file diff --git a/.gitignore b/.gitignore index e058206..23d5f03 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,5 @@ dist/ *.link -*.txt -/foundry # Dependency directories node_modules/ @@ -13,10 +11,3 @@ 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/foundry.html-data.json b/.vscode/foundry.html-data.json deleted file mode 100644 index 3358d2b..0000000 --- a/.vscode/foundry.html-data.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "version": 1.1, - "globalAttributes": [ - { "name": "data-tooltip", "description": "The content for the tooltip to display" }, - { "name": "data-tooltip-direction", "description": "The direction that the tooltip renders in, in relation to the element that has the tooltip", "valueSet": "tooltip-direction" } - ], - "valueSets": [ - { - "name": "tooltip-direction", - "values": [ - { "name": "UP", "description": "Put the tooltip above the element" }, - { "name": "LEFT", "description": "Put the tooltip to the left of the element" }, - { "name": "RIGHT", "description": "Put the tooltip to the right of element" }, - { "name": "DOWN", "description": "Put the tooltip below the element" } - ] - } - ] -} \ No newline at end of file diff --git a/.vscode/ripcrypt.html-data.json b/.vscode/ripcrypt.html-data.json deleted file mode 100644 index 3efb728..0000000 --- a/.vscode/ripcrypt.html-data.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "version": 1.1, - "tags": [ - { - "name": "rc-icon", - "description": "Loads an icon asynchronously, caching the result for future uses", - "attributes": [ - { "name": "name", "description": "The name of the icon, this is relative to the assets folder of the system" }, - { "name": "path", "description": "The full path of the icon, this will only be used if `name` isn't provided or fails to fetch." }, - { "name": "var:size", "description": "The size of the icon, must be a valid CSS unit" }, - { "name": "var:fill", "description": "The fill of the icon, must be a valid CSS colour" }, - { "name": "var:stroke", "description": "The stroke colour of the icon, must be a valid CSS colour" }, - { "name": "var:stroke-width", "description": "The stroke width of the icon, must be a valid CSS unit" }, - { "name": "var:stroke-linejoin", "description": "The stroke linejoin of the icon, must be a valid CSS value" } - ] - }, - { - "name": "rc-svg", - "description": "Loads an icon asynchronously, caching the result for future uses", - "attributes": [ - { "name": "name", "description": "The name of the icon, this is relative to the assets folder of the system" }, - { "name": "path", "description": "The full path of the icon, this will only be used if `name` isn't provided or fails to fetch." }, - { "name": "var:size", "description": "The size of the icon, must be a valid CSS unit" }, - { "name": "var:fill", "description": "The fill of the icon, must be a valid CSS colour" }, - { "name": "var:stroke", "description": "The stroke colour of the icon, must be a valid CSS colour" }, - { "name": "var:stroke-width", "description": "The stroke width of the icon, must be a valid CSS unit" }, - { "name": "var:stroke-linejoin", "description": "The stroke linejoin of the icon, must be a valid CSS value" } - ] - }, - { - "name": "rc-border", - "description": "Creates a stylized border in the same sort of design that the published RipCrypt book uses", - "attributes": [ - { "name": "var:vertical-displacement", "description": "How much vertical displacement the title receives, defaults to 12.5px" }, - { "name": "var:padding", "description": "How much padding the border container has" }, - { "name": "var:border-color", "description": "The CSS value that is used as the colour of the border" }, - { "name": "var:padding-top", "description": "How much padding the top of the border element has, if not provided, defaults to the value of vertical displacement plus 4px" }, - { "name": "var:margin-top", "description": "How much margin the top of the border element has, if not provided, defaults to the value of vertical displacement" }, - { "name": "var:border-mask", "description": "The CSS colour used to mask out the border element, if not provided defaults to the --base-background CSS variable"}, - { "name": "var:title-height", "description": "The CSS height for the title, defaults to 20px" }, - { "name": "var:title-background", "description": "The CSS colour to make the title element, defaults to var:border-color" } - ] - } - ] -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index c60389c..a72c23c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,17 +1,8 @@ { "files.exclude": { - "**/node_modules": true, - "foundry": true + "**/node_modules": true }, "search.exclude": { - "foundry": true - }, - "html.customData": [ - "./.vscode/foundry.html-data.json", - "./.vscode/ripcrypt.html-data.json" - ], - "workbench.editorAssociations": { - "*.svg": "default", - }, - "git.branchProtection": [] + "foundry.*.link": true + } } \ No newline at end of file diff --git a/README.md b/README.md index 6df788c..71abbda 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,2 @@ -# RipCrypt - A Dungeon Sprint RPG -RipCrypt is a fast, pick-up and play, tabletop RPG for 1-8 players. - -# Features: - -## Themes -The RipCrypt system comes with a dark and light theme for **everything** within the system! -All you need to do is select whichever theme you like more! - -## Hero Sheets -This system comes with multiple different Actor sheets for players -to make your experience, _yours_. - -Some of the sheets included by default are: -- Summary Card -- Skill Card -- Craft Card -- Full Sheet (Includes Summary Card & Skill Card) -- Tabbed Full Sheet (Includes Summary Card, Skill Card, and Craft Card as tabs within a single sheet) - -## Geist Sheets +# Foundry-RipCrypt +An implementation of the RipCrypt TTRPG System for FoundryVTT diff --git a/assets/_credit.txt b/assets/_credit.txt index 83c76aa..19babdc 100644 --- a/assets/_credit.txt +++ b/assets/_credit.txt @@ -1,34 +1,2 @@ -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. - -ARISO: - - icons/hourglass.svg (https://thenounproject.com/icon/hourglass-7546736/) : Rights Purchased - -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 - - icons/arrow-compass.svg (https://thenounproject.com/icon/arrow-2052607/) : Rights Purchased - Soetarman Atmodjo: - - icons/roll.svg (https://thenounproject.com/icon/dice-5195278/) : Rights Purchased - -SuperNdre: - - icons/edit.svg (https://thenounproject.com/icon/edit-5208207/) : Rights Purchased - -YANDI RS: - - icons/d8-outline.svg (https://thenounproject.com/icon/d8-7272826/) : Rights Purchased + - icons/roll.svg : Rights Purchased. diff --git a/assets/caster-silhouette.v1.svg b/assets/caster-silhouette.v1.svg deleted file mode 100644 index 9b53fcc..0000000 --- a/assets/caster-silhouette.v1.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assets/geist-silhouette.v2.svg b/assets/geist-silhouette.v2.svg deleted file mode 100644 index deb4cda..0000000 --- a/assets/geist-silhouette.v2.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assets/hero-silhouette.svg b/assets/hero-silhouette.svg deleted file mode 100644 index 12e2bb5..0000000 --- a/assets/hero-silhouette.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/assets/icons/arrow-compass.svg b/assets/icons/arrow-compass.svg deleted file mode 100644 index b1e8a40..0000000 --- a/assets/icons/arrow-compass.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/arrow-left.svg b/assets/icons/arrow-left.svg deleted file mode 100644 index e1a347e..0000000 --- a/assets/icons/arrow-left.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/arrow-right.svg b/assets/icons/arrow-right.svg deleted file mode 100644 index a477835..0000000 --- a/assets/icons/arrow-right.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/d8-outline.svg b/assets/icons/d8-outline.svg deleted file mode 100644 index 0346f4c..0000000 --- a/assets/icons/d8-outline.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/edit.svg b/assets/icons/edit.svg deleted file mode 100644 index acae8d6..0000000 --- a/assets/icons/edit.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/assets/icons/evil.svg b/assets/icons/evil.svg deleted file mode 100644 index 5d9fb11..0000000 --- a/assets/icons/evil.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/assets/icons/hero.svg b/assets/icons/hero.svg deleted file mode 100644 index 55de62b..0000000 --- a/assets/icons/hero.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/assets/icons/hourglass.svg b/assets/icons/hourglass.svg deleted file mode 100644 index 64ae5cf..0000000 --- a/assets/icons/hourglass.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/info-circle.svg b/assets/icons/info-circle.svg deleted file mode 100644 index 6e14569..0000000 --- a/assets/icons/info-circle.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/plus.svg b/assets/icons/plus.svg deleted file mode 100644 index 5e8c131..0000000 --- a/assets/icons/plus.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/roll.svg b/assets/icons/roll.svg index 51fb7ed..4d2a61b 100644 --- a/assets/icons/roll.svg +++ b/assets/icons/roll.svg @@ -1,4 +1,4 @@ - + diff --git a/assets/icons/shield-solid.svg b/assets/icons/shield-solid.svg deleted file mode 100644 index e9194e7..0000000 --- a/assets/icons/shield-solid.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/shield/checked.v1.svg b/assets/icons/shield/checked.v1.svg deleted file mode 100644 index c22ff10..0000000 --- a/assets/icons/shield/checked.v1.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/assets/icons/shield/crossed.v1.svg b/assets/icons/shield/crossed.v1.svg deleted file mode 100644 index bfcae76..0000000 --- a/assets/icons/shield/crossed.v1.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/assets/icons/shield/solid.v1.svg b/assets/icons/shield/solid.v1.svg deleted file mode 100644 index 7f37ece..0000000 --- a/assets/icons/shield/solid.v1.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/assets/icons/star-empty.svg b/assets/icons/star-empty.svg deleted file mode 100644 index 8760cc9..0000000 --- a/assets/icons/star-empty.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assets/icons/star.svg b/assets/icons/star.svg deleted file mode 100644 index 829431b..0000000 --- a/assets/icons/star.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assets/turn-marker.png b/assets/turn-marker.png deleted file mode 100644 index fa70749..0000000 Binary files a/assets/turn-marker.png and /dev/null differ diff --git a/augments.d.ts b/augments.d.ts deleted file mode 100644 index dc091c2..0000000 --- a/augments.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -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 4ef4c09..5cbe12c 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/`, `foundry/` ] }, + { ignores: [ `scripts/` ] }, { languageOptions: { globals: globals.browser, @@ -16,25 +16,20 @@ export default [ languageOptions: { globals: { CONFIG: `writable`, - CONST: `readonly`, game: `readonly`, Handlebars: `readonly`, Hooks: `readonly`, ui: `readonly`, Actor: `readonly`, + Actors: `readonly`, Item: `readonly`, + Items: `readonly`, foundry: `readonly`, ChatMessage: `readonly`, ActiveEffect: `readonly`, Dialog: `readonly`, renderTemplate: `readonly`, TextEditor: `readonly`, - fromUuid: `readonly`, - Combat: `readonly`, - Combatant: `readonly`, - canvas: `readonly`, - Token: `readonly`, - Tour: `readonly`, }, }, }, @@ -75,7 +70,7 @@ export default [ "@stylistic/eol-last": `warn`, "@stylistic/operator-linebreak": [`warn`, `before`], "@stylistic/indent": [`warn`, `tab`], - "@stylistic/brace-style": [`warn`, `stroustrup`, { "allowSingleLine": true }], + "@stylistic/brace-style": [`warn`, `1tbs`, { "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 47b5b55..8b0d1fc 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,19 +1,11 @@ { "compilerOptions": { - "module": "es2022", - "target": "es2022", - "types": [ - "./augments.d.ts" - ], - "paths": { - "@client/*": ["./foundry/client/*"], - "@common/*": ["./foundry/common/*"], - } + "module": "ES2020", + "target": "ES2020" }, - "include": [ - "module/**/*", - "foundry/client/client.mjs", - "foundry/client/global.d.mts", - "foundry/common/primitives/global.d.mts" - ] + "exclude": ["node_modules", "**/node_modules/*"], + "include": ["module/**/*", "foundry.v13.link/client/**/*.js", "foundry.v13.link/**/*.mjs"], + "typeAcquisition": { + "include": ["jquery"] + } } \ No newline at end of file diff --git a/langs/en-ca.json b/langs/en-ca.json index a5d28cc..460e963 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -1,229 +1,71 @@ { "TYPES": { "Actor": { - "hero": "Hero", - "geist": "Geist" + "hero": "Hero" }, "Item": { - "ammo": "Ammo", - "armour": "Armour", - "craft": "Craft", - "good": "Good", - "shield": "Shield", - "skill": "Skill", "weapon": "Weapon" } }, "RipCrypt": { "sheet-names": { - "AllItemsSheetV1": "RipCrypt Item Sheet", - "ArmourSheet": "Armour Sheet", - "CombinedHeroSheet": "Hero Sheet", - "StatsCardV1": "Hero Stat Card", - "CraftCardV1": "Hero Craft Card", - "SkillsCardV1": "Hero Skill Card" - }, - "app-titles": { - "AmmoTracker": "Ammo Tracker" + "HeroSummaryCardV1": "Hero Stat Card", + "HeroSkillsCardV1": "Hero Skill Card" }, "common": { - "abilities": { + "empty": "---", + "move": "Move", + "run": "Run", + "fate": { + "North": "North", + "East": "East", + "South": "South", + "West": "West" + }, + "ability": { "grit": "Grit", "gait": "Gait", "grip": "Grip", - "glim": "Glim", - "thin-glim": "Thin Glim" + "glim": "Glim" }, - "ability": "Ability", - "access": "Access", - "accessLevels": { - "Common": "Common", - "Uncommon": "Uncommon", - "Rare": "Rare", - "Scarce": "Scarce" - }, - "advances": "Advances", - "ammo": "Ammo", - "anatomy": { - "head": "Head", - "body": "Body", - "arms": "Arms", - "legs": "Legs" - }, - "armour": "Armour", - "aspect": "Aspect", - "aspectNames": { - "flect": "Flect", - "fract": "Fract", - "focus": "Focus" - }, - "aura": "Aura", - "cost": "Cost", - "currency": { - "gold": "Gold", - "silver": "Silver", - "copper": "Copper" - }, - "damage": "Damage", - "delete": "Delete", - "description": "Description", - "details": "Details", - "difficulties": { - "easy": "Easy", - "normal": "Normal", - "tough": "Tough", - "hard": "Hard", - "random": "Random Condition" - }, - "difficulty": "Difficulty", - "drag": "Drag", - "edit": "Edit", - "edge": "Edge", - "empty": "---", - "equipped": "Equipped", - "fate": "Fate", - "gear": "Gear", - "glimcraft": "Glimcraft", - "glory": "Glory", - "guts": "Guts", - "location": "Location", - "move": "Move", - "ordinals": { - "North": { - "full": "North", - "abbv": "N" - }, - "East": { - "full": "East", - "abbv": "E" - }, - "South": { - "full": "South", - "abbv": "S" - }, - "West": { - "full": "West", - "abbv": "W" - } - }, - "protection": "Protection", - "quantity": "Quantity", - "rank": "Rank", - "rankNames": { - "novice": "Novice", - "adept": "Adept", - "expert": "Expert", - "master": "Master" - }, - "range": "Range", - "run": "Run", - "shield": "Shield", - "slot": "Slot", - "step": "Step", "traits": "Traits", + "range": "Range", "weapon": { "singular": "Weapon", "plural": "Weapons" }, "wear": "Wear", - "weightRating": "Weight", - "weightRatings": { - "light": "Light", - "modest": "Modest", - "heavy": "Heavy" + "damage": "Damage", + "guts": "Guts", + "glory": "Glory", + "step": "Step", + "rank": "Rank", + "gear": "Gear", + "slot": "Slot", + "currency": { + "gold": "Gold", + "silver": "Silver", + "copper": "Copper" } }, "setting": { "abbrAccess": { "name": "Abbreviate Access Names", "hint": "Shortens the Access level names the way the book does. (e.g. \"Common\" becomes \"C\")" - }, - "condensedRange": { - "name": "Condense Weapon Range Input", - "hint": "With this enabled, the weapon range will be displayed as \"X / Y\" when editing a weapon. While disabled it will be as displayed as two different rows, one for Short Range and one for Long Range" - }, - "sandsOfFateInitial": { - "name": "Sands of Fate Initial", - "hint": "What value should The Hourglass reset to when a Cryptic Event occurs" - }, - "onCrypticEvent": { - "name": "Cryptic Event Alert", - "hint": "What happens when a cryptic event occurs by clicking the \"Next Delve Tour\" button in the HUD", - "options": { - "notif": "Notification", - "pause": "Pause Game", - "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", - "grip-skills": "@RipCrypt.common.abilities.grip Skills", - "glim-skills": "@RipCrypt.common.abilities.glim Skills", + "move-run": "@RipCrypt.common.move • @RipCrypt.common.run", + "traits-range": "@RipCrypt.common.traits • @RipCrypt.common.range", + "grit-skills": "@RipCrypt.common.ability.grit Skills", + "gait-skills": "@RipCrypt.common.ability.gait Skills", + "grip-skills": "@RipCrypt.common.ability.grip Skills", + "glim-skills": "@RipCrypt.common.ability.glim Skills", "a11y": { "guts-value-edit": "The current amount of guts the character has", "guts-value-readonly": "The current amount of guts the character has", "guts-max-readonly": "The maximum amount of guts the character can have" - }, - "traits-placeholder": "New Trait...", - "short-range": "Short @RipCrypt.common.range", - "long-range": "Long @RipCrypt.common.range", - "current-wear": "Current @RipCrypt.common.wear", - "max-wear": "Maximum @RipCrypt.common.wear", - "location-placeholder": "New Location...", - "numberOfDice": "# of Dice", - "rollTarget": "Target", - "difficulty": "(DC: {dc})", - "RichEditor-no-collaborative": "Warning: This editor is not collaborative, that means that if you and someone else are editing it at the same time, you won't see that someone else is making changes until they save, and then your changes will be lost.", - "starred-ammo-placeholder": "Starred Ammo Slot", - "AmmoTracker": { - "no-ammo": "You don't have any ammo!", - "star-button": "Add {name} as a starred ammo", - "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.", - "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." - }, - "info": { - "cryptic-event-alert": "A Cryptic Event Has Occured!" - } - }, - "tooltips": { - "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": { - "normal": "The distance of your aura normally", - "heavy": "The distance of your aura when using Heavycraft" } } - }, - "USER": { - "GM": "Keeper" } } diff --git a/module/Apps/ActorSheets/CombinedHeroSheet.mjs b/module/Apps/ActorSheets/CombinedHeroSheet.mjs deleted file mode 100644 index b81923a..0000000 --- a/module/Apps/ActorSheets/CombinedHeroSheet.mjs +++ /dev/null @@ -1,116 +0,0 @@ -import { CraftCardV1 } from "./CraftCardV1.mjs"; -import { filePath } from "../../consts.mjs"; -import { GenericAppMixin } from "../GenericApp.mjs"; -import { SkillsCardV1 } from "./SkillsCardV1.mjs"; -import { StatsCardV1 } from "./StatsCardV1.mjs"; - -const { HandlebarsApplicationMixin } = foundry.applications.api; -const { ActorSheetV2 } = foundry.applications.sheets; - -export class CombinedHeroSheet extends GenericAppMixin(HandlebarsApplicationMixin(ActorSheetV2)) { - - // #region Options - static DEFAULT_OPTIONS = { - classes: [ - `ripcrypt--actor`, - `ripcrypt--CombinedHeroSheet`, - ], - position: { - width: `auto`, - height: `auto`, - }, - window: { - resizable: false, - }, - actions: { - ...StatsCardV1.DEFAULT_OPTIONS.actions, - }, - form: { - submitOnChange: true, - closeOnSubmit: false, - }, - }; - - static PARTS = { - summary: { - template: filePath(`templates/Apps/StatsCardV1/content.hbs`), - }, - skills: { - template: filePath(`templates/Apps/SkillsCardV1/content.hbs`), - }, - craft: { - template: filePath(`templates/Apps/CombinedHeroSheet/crafts.hbs`), - }, - }; - // #endregion - - // #region Lifecycle - async _onRender(context, options) { - await super._onRender(context, options); - - const summaryElement = this.element.querySelector(`.StatsCardV1`); - StatsCardV1._onRender( - context, - { - ...options, - element: summaryElement, - isEditable: this.isEditable, - }, - ); - - const skillsElement = this.element.querySelector(`.SkillsCardV1`); - SkillsCardV1._createPopoverListeners.bind(this)(); - SkillsCardV1._onRender.bind(this)( - context, - { - ...options, - element: skillsElement, - isEditable: this.isEditable, - }, - ); - - const craftsElement = this.element.querySelector(`.crafts-summary`); - CraftCardV1._onRender.bind(this)( - context, - { - ...options, - element: craftsElement, - isEditable: this.isEditable, - }, - ); - }; - - async _preparePartContext(partId, ctx, opts) { - ctx = await super._preparePartContext(partId, ctx, opts); - ctx.actor = this.document; - - switch (partId) { - case `summary`: { - ctx = await StatsCardV1.prepareGuts(ctx); - ctx = await StatsCardV1.prepareWeapons(ctx); - ctx = await StatsCardV1.prepareArmor(ctx); - ctx = await StatsCardV1.prepareFatePath(ctx); - ctx = await StatsCardV1.prepareAbilityRow(ctx); - ctx = await StatsCardV1.prepareSpeed(ctx); - ctx = await StatsCardV1.prepareLevelData(ctx); - break; - }; - case `skills`: { - ctx = await SkillsCardV1.prepareGear(ctx); - ctx = await SkillsCardV1.prepareAmmo(ctx); - ctx = await SkillsCardV1.prepareSkills(ctx); - break; - }; - case `craft`: { - ctx = await CraftCardV1.prepareCraft(ctx); - break; - }; - }; - - return ctx; - }; - // #endregion - - // #region Actions - // #endregion -}; diff --git a/module/Apps/ActorSheets/CraftCardV1.mjs b/module/Apps/ActorSheets/CraftCardV1.mjs deleted file mode 100644 index 4a650df..0000000 --- a/module/Apps/ActorSheets/CraftCardV1.mjs +++ /dev/null @@ -1,133 +0,0 @@ -import { deleteItemFromElement, editItemFromElement } from "../utils.mjs"; -import { documentSorter, filePath } from "../../consts.mjs"; -import { gameTerms } from "../../gameTerms.mjs"; -import { GenericAppMixin } from "../GenericApp.mjs"; -import { localizer } from "../../utils/Localizer.mjs"; -import { Logger } from "../../utils/Logger.mjs"; - -const { HandlebarsApplicationMixin } = foundry.applications.api; -const { ActorSheetV2 } = foundry.applications.sheets; -const { ContextMenu } = foundry.applications.ux; -const { deepClone } = foundry.utils; - -export class CraftCardV1 extends GenericAppMixin(HandlebarsApplicationMixin(ActorSheetV2)) { - - // #region Options - static DEFAULT_OPTIONS = { - classes: [ - `ripcrypt--actor`, - `ripcrypt--CraftCardV1`, - ], - position: { - width: `auto`, - height: `auto`, - }, - window: { - resizable: false, - }, - actions: { - }, - form: { - submitOnChange: true, - closeOnSubmit: false, - }, - }; - - static PARTS = { - content: { - template: filePath(`templates/Apps/CraftCardV1/content.hbs`), - }, - }; - // #endregion - - // #region Lifecycle - async _onRender(context, options) { - await super._onRender(context, options); - CraftCardV1._onRender.bind(this)(context, options); - }; - - static async _onRender(_context, options) { - const { - element = this.element, - isEditable = this.isEditable, - } = options; - new ContextMenu( - element, - `[data-ctx-menu="craft"]`, - [ - { - name: localizer(`RipCrypt.common.edit`), - condition: (el) => { - const itemId = el.dataset.itemId; - return isEditable && itemId !== ``; - }, - callback: editItemFromElement, - }, - { - name: localizer(`RipCrypt.common.delete`), - condition: (el) => { - const itemId = el.dataset.itemId; - return isEditable && itemId !== ``; - }, - callback: deleteItemFromElement, - }, - ], - { jQuery: false, fixed: true }, - ); - }; - - async _preparePartContext(partId, ctx, opts) { - ctx = await super._preparePartContext(partId, ctx, opts); - ctx.actor = this.document; - - ctx = await CraftCardV1.prepareAura(ctx); - ctx = await CraftCardV1.prepareCraft(ctx); - - Logger.debug(`Context:`, ctx); - return ctx; - }; - - static async prepareAura(ctx) { - ctx.aura = deepClone(ctx.actor.system.aura); - return ctx; - }; - - static async prepareCraft(ctx) { - ctx.craft = {}; - const aspects = Object.values(gameTerms.Aspects); - const heroRank = ctx.actor.system.level.rank; - const embeddedCrafts = ctx.actor.itemTypes.craft; - const limit = 4; - - for (const aspect of aspects) { - let crafts = []; - for (const craft of embeddedCrafts) { - if (craft.system.aspect !== aspect) { continue }; - crafts.push({ - uuid: craft.uuid, - name: craft.name, - sort: craft.sort, - use: craft.system.advances[heroRank], - }); - }; - - // Ensure limit isn't surpassed - const length = crafts.length; - if (length >= limit) { - crafts = crafts.slice(0, limit); - } - else { - crafts = crafts - .concat(Array(limit - length).fill(null)) - .slice(0, limit); - }; - - ctx.craft[aspect] = crafts.sort(documentSorter); - } - return ctx; - }; - // #endregion - - // #region Actions - // #endregion -}; diff --git a/module/Apps/ActorSheets/HeroSkillsCardV1.mjs b/module/Apps/ActorSheets/HeroSkillsCardV1.mjs new file mode 100644 index 0000000..9b55105 --- /dev/null +++ b/module/Apps/ActorSheets/HeroSkillsCardV1.mjs @@ -0,0 +1,52 @@ +import { filePath } from "../../consts.mjs"; +import { gameTerms } from "../../gameTerms.mjs"; +import { GenericAppMixin } from "../GenericApp.mjs"; +import { localizer } from "../../utils/Localizer.mjs"; +import { Logger } from "../../utils/Logger.mjs"; + +const { HandlebarsApplicationMixin } = foundry.applications.api; +const { ActorSheetV2 } = foundry.applications.sheets; + +export class HeroSkillsCardV1 extends GenericAppMixin(HandlebarsApplicationMixin(ActorSheetV2)) { + + // #region Options + static DEFAULT_OPTIONS = { + classes: [ + `ripcrypt--actor`, + `ripcrypt--HeroSkillsCardV1`, + ], + position: { + width: `auto`, + height: `auto`, + }, + window: { + resizable: false, + }, + actions: { + }, + form: { + submitOnChange: true, + closeOnSubmit: false, + }, + }; + + static PARTS = { + content: { + template: filePath(`templates/Apps/HeroSkillsCardV1/content.hbs`), + }, + }; + // #endregion + + // #region Lifecycle + async _preparePartContext(partId, ctx, opts) { + ctx = await super._preparePartContext(partId, ctx, opts); + ctx.actor = this.document; + + Logger.debug(`Context:`, ctx); + return ctx; + }; + // #endregion + + // #region Actions + // #endregion +}; diff --git a/module/Apps/ActorSheets/HeroSummaryCardV1.mjs b/module/Apps/ActorSheets/HeroSummaryCardV1.mjs new file mode 100644 index 0000000..c38b6f4 --- /dev/null +++ b/module/Apps/ActorSheets/HeroSummaryCardV1.mjs @@ -0,0 +1,139 @@ +import { filePath } from "../../consts.mjs"; +import { gameTerms } from "../../gameTerms.mjs"; +import { GenericAppMixin } from "../GenericApp.mjs"; +import { localizer } from "../../utils/Localizer.mjs"; +import { Logger } from "../../utils/Logger.mjs"; + +const { HandlebarsApplicationMixin } = foundry.applications.api; +const { ActorSheetV2 } = foundry.applications.sheets; + +export class HeroSummaryCardV1 extends GenericAppMixin(HandlebarsApplicationMixin(ActorSheetV2)) { + + // #region Options + static DEFAULT_OPTIONS = { + classes: [ + `ripcrypt--actor`, + `ripcrypt--HeroSummaryCardV1`, + ], + position: { + width: `auto`, + height: `auto`, + }, + window: { + resizable: false, + }, + actions: {}, + form: { + submitOnChange: true, + closeOnSubmit: false, + }, + }; + + static PARTS = { + content: { + template: filePath(`templates/Apps/HeroSummaryCardV1/content.hbs`), + }, + }; + // #endregion + + // #region Lifecycle + async _preparePartContext(partId, ctx, opts) { + ctx = await super._preparePartContext(partId, ctx, opts); + ctx.actor = this.document; + + ctx = await HeroSummaryCardV1.prepareGuts(ctx); + ctx = await HeroSummaryCardV1.prepareWeapons(ctx); + ctx = await HeroSummaryCardV1.prepareFatePath(ctx); + ctx = await HeroSummaryCardV1.prepareAbilityRow(ctx); + ctx = await HeroSummaryCardV1.prepareSpeed(ctx); + ctx = await HeroSummaryCardV1.prepareLevelData(ctx); + + Logger.debug(`Context:`, ctx); + return ctx; + }; + + static async prepareLevelData(ctx) { + ctx.level = { + glory: ctx.actor.system.level.glory, + step: ctx.actor.system.level.step, + rank: { + selected: ctx.actor.system.level.rank, + options: Object.values(gameTerms.Rank), + }, + }; + if (ctx.meta.limited) { + ctx.level.glory = `?`; + ctx.level.step = `?`; + ctx.level.rank.selected = `?`; + }; + return ctx; + }; + + static async prepareFatePath(ctx) { + ctx.fate = {}; + ctx.fate.selected = ctx.actor.system.fate; + ctx.fate.options = [ + { label: `RipCrypt.common.empty`, v: `` }, + ...gameTerms.FatePath + .map(v => ({ label: `RipCrypt.common.fate.${v}`, value: v })), + ]; + return ctx; + }; + + static async prepareAbilityRow(ctx) { + ctx.abilities = []; + for (const key in ctx.actor.system.ability) { + ctx.abilities.push({ + id: key, + name: localizer( + `RipCrypt.common.ability.${key}`, + { value: ctx.actor.system.ability[key] }, + ), + value: ctx.meta.limited ? `?` : ctx.actor.system.ability[key], + readonly: !ctx.meta.editable, + }); + }; + return ctx; + }; + + static async prepareSpeed(ctx) { + ctx.speed = foundry.utils.deepClone(ctx.actor.system.speed); + if (ctx.meta.limited) { + ctx.speed = { + move: `?`, + run: `?`, + }; + }; + return ctx; + }; + + static async prepareWeapons(ctx) { + const limit = ctx.actor.system.limit.weapons; + const embedded = ctx.actor.itemTypes.weapon; + ctx.weapons = []; + for (let i = 0; i < limit; i++) { + ctx.weapons.push({ + data: embedded[i], + empty: embedded.at(i) === undefined, + index: i + 1, + class: i % 2 === 1 ? `row-alt` : ``, + }); + }; + return ctx; + }; + + static async prepareGuts(ctx) { + ctx.guts = foundry.utils.deepClone(ctx.actor.system.guts); + if (ctx.meta.limited) { + ctx.guts = { + value: `?`, + max: `?`, + }; + }; + return ctx; + }; + // #endregion + + // #region Actions + // #endregion +}; diff --git a/module/Apps/ActorSheets/SkillsCardV1.mjs b/module/Apps/ActorSheets/SkillsCardV1.mjs deleted file mode 100644 index b0231f3..0000000 --- a/module/Apps/ActorSheets/SkillsCardV1.mjs +++ /dev/null @@ -1,213 +0,0 @@ -import { deleteItemFromElement, editItemFromElement } from "../utils.mjs"; -import { documentSorter, filePath } from "../../consts.mjs"; -import { AmmoTracker } from "../popovers/AmmoTracker.mjs"; -import { gameTerms } from "../../gameTerms.mjs"; -import { GenericAppMixin } from "../GenericApp.mjs"; -import { ItemFlags } from "../../flags/item.mjs"; -import { localizer } from "../../utils/Localizer.mjs"; -import { Logger } from "../../utils/Logger.mjs"; -import { PopoverEventManager } from "../../utils/PopoverEventManager.mjs"; - -const { HandlebarsApplicationMixin } = foundry.applications.api; -const { ActorSheetV2 } = foundry.applications.sheets; -const { ContextMenu } = foundry.applications.ux; -const { deepClone } = foundry.utils; - -export class SkillsCardV1 extends GenericAppMixin(HandlebarsApplicationMixin(ActorSheetV2)) { - - // #region Options - static DEFAULT_OPTIONS = { - classes: [ - `ripcrypt--actor`, - `ripcrypt--SkillsCardV1`, - ], - position: { - width: `auto`, - height: `auto`, - }, - window: { - resizable: false, - }, - actions: { - }, - form: { - submitOnChange: true, - closeOnSubmit: false, - }, - }; - - static PARTS = { - content: { - template: filePath(`templates/Apps/SkillsCardV1/content.hbs`), - }, - }; - // #endregion - - // #region Lifecycle - async _onRender(context, options) { - await super._onRender(context, options); - SkillsCardV1._onRender.bind(this)(context, options); - SkillsCardV1._createPopoverListeners.bind(this)(); - }; - - static async _onRender(_context, options) { - const { - element = this.element, - isEditable = this.isEditable, - } = options; - new ContextMenu( - element, - `[data-ctx-menu="gear"],[data-ctx-menu="skill"]`, - [ - { - name: localizer(`RipCrypt.common.edit`), - condition: (el) => { - const itemId = el.dataset.itemId; - return isEditable && itemId !== ``; - }, - callback: editItemFromElement, - }, - { - name: localizer(`RipCrypt.common.delete`), - condition: (el) => { - const itemId = el.dataset.itemId; - return isEditable && itemId !== ``; - }, - callback: deleteItemFromElement, - }, - ], - { jQuery: false, fixed: true }, - ); - }; - - /** @this {SkillsCardV1} */ - static async _createPopoverListeners() { - const ammoInfoIcon = this.element.querySelector(`.ammo-info-icon`); - const idPrefix = this.actor.uuid; - - const manager = new PopoverEventManager(`${idPrefix}.ammo-info-icon`, ammoInfoIcon, AmmoTracker); - this._popoverManagers.set(`.ammo-info-icon`, manager); - this._hookIDs.set(Hooks.on(`prepare${manager.id}Context`, (ctx) => { - ctx.ammos = this.actor.itemTypes.ammo; - }), `prepare${manager.id}Context`); - }; - - async _preparePartContext(partId, ctx, opts) { - ctx = await super._preparePartContext(partId, ctx, opts); - ctx.actor = this.document; - - ctx = await SkillsCardV1.prepareGear(ctx); - ctx = await SkillsCardV1.prepareAmmo(ctx); - ctx = await SkillsCardV1.prepareSkills(ctx); - - ctx.aura = deepClone(ctx.actor.system.aura); - - Logger.debug(`Context:`, ctx); - return ctx; - }; - - static async prepareGear(ctx) { - const limit = ctx.actor.system.limit.equipment; - ctx.gear = []; - const items = [...ctx.actor.items]; - for (const item of items) { - if (!gameTerms.gearItemTypes.has(item.type)) { continue }; - - if (`equipped` in item.system && item.system.equipped) { continue }; - ctx.gear.push({ - index: ctx.gear.length, - uuid: item.uuid, - name: item.quantifiedName, - empty: false, - }); - - if (ctx.gear.length >= limit) { break }; - }; - - if (ctx.gear.length < limit) { - for (let i = ctx.gear.length; i < limit; i++) { - ctx.gear.push({ - index: ctx.gear.length, - uuid: ``, - name: ``, - empty: true, - }); - }; - }; - - return ctx; - }; - - static async prepareAmmo(ctx) { - let total = 0; - let favouriteCount = 0; - ctx.favouriteAmmo = new Array(3).fill(null); - - for (const ammo of ctx.actor.itemTypes.ammo) { - total += ammo.system.quantity; - - if (favouriteCount < 3 && ammo.getFlag(game.system.id, ItemFlags.FAVOURITE)) { - ctx.favouriteAmmo[favouriteCount] = { - uuid: ammo.uuid, - name: ammo.name, - quantity: ammo.system.quantity, - }; - favouriteCount++; - }; - }; - - ctx.ammo = total; - return ctx; - }; - - static async prepareSkills(ctx) { - ctx.skills = {}; - const abilities = Object.values(gameTerms.Abilities); - const heroRank = ctx.actor.system.level.rank; - const embeddedSkills = ctx.actor.itemTypes.skill; - - for (let ability of abilities) { - const skills = []; - for (const skill of embeddedSkills) { - if (skill.system.ability !== ability) { continue }; - skills.push({ - uuid: skill.uuid, - name: skill.name, - sort: skill.sort, - use: skill.system.advances[heroRank], - }); - }; - - // Thin Glim is grouped with full glim. - if (ability === gameTerms.Abilities.THINGLIM) { - ability = gameTerms.Abilities.GLIM; - }; - - ctx.skills[ability] ??= []; - ctx.skills[ability].push(...skills); - }; - - const limit = ctx.actor.system.limit.skills; - for (const ability of abilities) { - if (ctx.skills[ability] == null) { continue }; - - const length = ctx.skills[ability].length; - if (length >= limit) { - ctx.skills[ability] = ctx.skills[ability].slice(0, limit); - } - else { - ctx.skills[ability] = ctx.skills[ability] - .concat(Array(limit - length).fill(null)) - .slice(0, limit); - }; - - // Sort the skills - ctx.skills[ability] = ctx.skills[ability].sort(documentSorter); - } - return ctx; - }; - // #endregion - - // #region Actions - // #endregion -}; diff --git a/module/Apps/ActorSheets/StatsCardV1.mjs b/module/Apps/ActorSheets/StatsCardV1.mjs deleted file mode 100644 index cd44ead..0000000 --- a/module/Apps/ActorSheets/StatsCardV1.mjs +++ /dev/null @@ -1,225 +0,0 @@ -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"; -import { localizer } from "../../utils/Localizer.mjs"; -import { Logger } from "../../utils/Logger.mjs"; - -const { HandlebarsApplicationMixin } = foundry.applications.api; -const { ActorSheetV2 } = foundry.applications.sheets; -const { ContextMenu } = foundry.applications.ux; - -export class StatsCardV1 extends GenericAppMixin(HandlebarsApplicationMixin(ActorSheetV2)) { - - // #region Options - static DEFAULT_OPTIONS = { - classes: [ - `ripcrypt--actor`, - `ripcrypt--StatsCardV1`, - ], - position: { - width: `auto`, - height: `auto`, - }, - window: { - resizable: false, - }, - actions: { - rollForHaste: DelveDiceHUD.rollForHaste, - }, - form: { - submitOnChange: true, - closeOnSubmit: false, - }, - }; - - static PARTS = { - content: { - template: filePath(`templates/Apps/StatsCardV1/content.hbs`), - }, - }; - // #endregion - - // #region Lifecycle - async _onRender(context, options) { - await super._onRender(context, options); - StatsCardV1._onRender.bind(this)(context, options); - }; - - static async _onRender(context, options) { - const { - element = this.element, - isEditable = this.isEditable, - } = options; - new ContextMenu( - element, - `[data-ctx-menu="weapon"],[data-ctx-menu="armour"]`, - [ - { - name: localizer(`RipCrypt.common.edit`), - condition: (el) => { - const itemId = el.dataset.itemId; - return isEditable && itemId !== ``; - }, - callback: editItemFromElement, - }, - { - name: localizer(`RipCrypt.common.delete`), - condition: (el) => { - const itemId = el.dataset.itemId; - return isEditable && itemId !== ``; - }, - callback: deleteItemFromElement, - }, - ], - { jQuery: false, fixed: true }, - ); - }; - - async _preparePartContext(partId, ctx, opts) { - ctx = await super._preparePartContext(partId, ctx, opts); - ctx.actor = this.document; - - ctx = await StatsCardV1.prepareGuts(ctx); - ctx = await StatsCardV1.prepareWeapons(ctx); - ctx = await StatsCardV1.prepareArmor(ctx); - ctx = await StatsCardV1.prepareFatePath(ctx); - ctx = await StatsCardV1.prepareAbilityRow(ctx); - ctx = await StatsCardV1.prepareSpeed(ctx); - ctx = await StatsCardV1.prepareLevelData(ctx); - - Logger.debug(`Context:`, ctx); - return ctx; - }; - - static async prepareLevelData(ctx) { - ctx.level = { - glory: ctx.actor.system.level.glory, - step: ctx.actor.system.level.step, - rank: { - selected: ctx.actor.system.level.rank, - options: Object.values(gameTerms.Rank).map(rank => ({ - label: `RipCrypt.common.rankNames.${rank}`, - value: rank, - })), - }, - }; - if (ctx.meta.limited) { - ctx.level.glory = `?`; - ctx.level.step = `?`; - ctx.level.rank.selected = `?`; - }; - return ctx; - }; - - static async prepareFatePath(ctx) { - ctx.fate = {}; - ctx.fate.selected = ctx.actor.system.fate; - ctx.fate.options = [ - { label: `RipCrypt.common.empty`, v: `` }, - ...Object.values(gameTerms.FatePath) - .map(v => ({ label: `RipCrypt.common.ordinals.${v}.full`, value: v })), - ]; - return ctx; - }; - - static async prepareAbilityRow(ctx) { - ctx.abilities = []; - for (const key in ctx.actor.system.ability) { - ctx.abilities.push({ - id: key, - name: localizer( - `RipCrypt.common.abilities.${key}`, - { value: ctx.actor.system.ability[key] }, - ), - value: ctx.meta.limited ? `?` : ctx.actor.system.ability[key], - readonly: !ctx.meta.editable, - }); - }; - return ctx; - }; - - static async prepareSpeed(ctx) { - ctx.speed = foundry.utils.deepClone(ctx.actor.system.speed); - if (ctx.meta.limited) { - ctx.speed = { - move: `?`, - run: `?`, - }; - }; - return ctx; - }; - - static async prepareArmor(ctx) { - ctx.armours = {}; - const equipped = ctx.actor.system.equippedArmour; - const shield = ctx.actor.system.equippedShield; - const defenses = ctx.actor.system.defense; - for (const slot of Object.values(gameTerms.Anatomy)) { - const item = equipped[slot]; - ctx.armours[slot] = { - name: item?.name ?? ``, - uuid: item?.uuid ?? ``, - defense: defenses[slot], - shielded: shield?.system.location.has(slot) ?? false, - }; - }; - - ctx.shield = { - name: shield?.name ?? ``, - uuid: shield?.uuid ?? ``, - bonus: shield?.system.protection ?? 0, - }; - - return ctx; - }; - - static async prepareWeapons(ctx) { - const limit = ctx.actor.system.limit.weapons; - const embedded = ctx.actor.itemTypes.weapon; - ctx.weapons = []; - for (const item of embedded) { - if (!item.system.equipped) { continue }; - - const index = ctx.weapons.length; - ctx.weapons.push({ - data: item, - empty: false, - index, - class: index % 2 === 1 ? `row-alt` : ``, - }); - - if (ctx.weapons.length >= limit) { break }; - }; - - if (ctx.weapons.length < limit) { - for (let i = ctx.weapons.length; i < limit; i++) { - const itemIndex = ctx.weapons.length; - ctx.weapons.push({ - data: null, - empty: true, - index: itemIndex, - class: itemIndex % 2 === 1 ? `row-alt` : ``, - }); - }; - }; - - return ctx; - }; - - static async prepareGuts(ctx) { - ctx.guts = foundry.utils.deepClone(ctx.actor.system.guts); - if (ctx.meta.limited) { - ctx.guts = { - value: `?`, - max: `?`, - }; - }; - return ctx; - }; - // #endregion - - // #region Actions - // #endregion -}; diff --git a/module/Apps/CryptApp.mjs b/module/Apps/CryptApp.mjs new file mode 100644 index 0000000..a4c3053 --- /dev/null +++ b/module/Apps/CryptApp.mjs @@ -0,0 +1,43 @@ +import { filePath } from "../consts.mjs"; +import { GenericAppMixin } from "./GenericApp.mjs"; +import { Logger } from "../utils/Logger.mjs"; + +const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; + +export class CryptApp extends GenericAppMixin(HandlebarsApplicationMixin(ApplicationV2)) { + // #region Options + static DEFAULT_OPTIONS = { + window: { + title: `Crypt Overview`, + frame: true, + positioned: true, + resizable: false, + minimizable: true, + }, + actions: {}, + }; + + static PARTS = { + main: { + template: filePath(`templates/Apps/CryptApp/main.hbs`), + }, + }; + // #endregion + + // #region Lifecycle + async _renderFrame(options) { + const frame = await super._renderFrame(options); + this.window.close.remove(); // Prevent closing + return frame; + }; + + async _preparePartContext(partId, ctx, opts) { + ctx = await super._preparePartContext(partId, ctx, opts); + Logger.log(`Context`, ctx); + return ctx; + }; + // #endregion + + // #region Actions + // #endregion +}; diff --git a/module/Apps/DelveDiceHUD.mjs b/module/Apps/DelveDiceHUD.mjs deleted file mode 100644 index 9599fa1..0000000 --- a/module/Apps/DelveDiceHUD.mjs +++ /dev/null @@ -1,305 +0,0 @@ -import { distanceBetweenFates, nextFate, previousFate } from "../utils/fates.mjs"; -import { filePath } from "../consts.mjs"; -import { gameTerms } from "../gameTerms.mjs"; -import { localizer } from "../utils/Localizer.mjs"; -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 = { - [FatePath.NORTH]: -90, - [FatePath.EAST]: 0, - [FatePath.SOUTH]: 90, - [FatePath.WEST]: 180, -}; - -const conditions = [ - { label: `RipCrypt.common.difficulties.easy`, value: 4 }, - { label: `RipCrypt.common.difficulties.normal`, value: 5 }, - { label: `RipCrypt.common.difficulties.tough`, value: 6 }, - { label: `RipCrypt.common.difficulties.hard`, value: 7 }, -]; - -export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) { - // #region Options - static DEFAULT_OPTIONS = { - id: `ripcrypt-delve-dice`, - tag: `aside`, - classes: [ - `ripcrypt`, - `ripcrypt--DelveDiceHUD`, - `hud`, - ], - window: { - frame: false, - positioned: false, - }, - actions: { - tourDelta: this.#tourDelta, - setFate: this.#setFate, - }, - }; - - static PARTS = { - previousTour: { - template: filePath(`templates/Apps/DelveDiceHUD/tour/previous.hbs`), - }, - difficulty: { - template: filePath(`templates/Apps/DelveDiceHUD/difficulty.hbs`), - }, - fateCompass: { - template: filePath(`templates/Apps/DelveDiceHUD/fateCompass.hbs`), - }, - sandsOfFate: { - template: filePath(`templates/Apps/DelveDiceHUD/tour/current.hbs`), - }, - nextTour: { - template: filePath(`templates/Apps/DelveDiceHUD/tour/next.hbs`), - }, - }; - // #endregion - - // #region Instance Data - /** - * The current number of degrees the compass pointer should be rotated, this - * is not stored in the DB since we only care about the initial rotation on - * reload, which is derived from the current fate. - * @type {Number} - */ - _rotation; - - constructor(...args) { - super(...args); - this._sandsOfFate = game.settings.get(`ripcrypt`, `sandsOfFate`); - this._currentFate = game.settings.get(`ripcrypt`, `currentFate`); - this._rotation = CompassRotations[this._currentFate]; - this._difficulty = game.settings.get(`ripcrypt`, `dc`); - }; - // #endregion - - // #region Lifecycle - /** - * Injects the element into the Foundry UI in the top middle - */ - _insertElement(element) { - const existing = document.getElementById(element.id); - if (existing) { - existing.replaceWith(element); - } - else { - const parent = document.getElementById(`ui-top`); - parent.prepend(element); - }; - }; - - async _onRender(context, options) { - await super._onRender(context, options); - - // Shortcut because users can't edit - if (!game.user.isGM) { return }; - - new ContextMenu( - this.element, - `#delve-difficulty`, - [ - ...conditions.map(condition => ({ - name: localizer(condition.label), - callback: DelveDiceHUD.#setDifficulty.bind(this, condition.value), - })), - { - name: localizer(`RipCrypt.common.difficulties.random`), - callback: () => { - const condition = conditions[Math.floor(Math.random() * conditions.length)]; - DelveDiceHUD.#setDifficulty.bind(this)(condition.value); - }, - }, - ], - { jQuery: false, fixed: true }, - ); - }; - - async _preparePartContext(partId, ctx, opts) { - ctx = await super._preparePartContext(partId, ctx, opts); - ctx.meta ??= {}; - - ctx.meta.editable = game.user.isGM; - - switch (partId) { - case `sandsOfFate`: { - ctx.sandsOfFate = this._sandsOfFate; - break; - }; - case `difficulty`: { - ctx.dc = this._difficulty; - break; - }; - case `fateCompass`: { - ctx.fate = this._currentFate; - ctx.rotation = `${this._rotation}deg`; - break; - }; - }; - - Logger.log(`${partId} Context`, ctx); - return ctx; - }; - - async animate({ parts = [] } = {}) { - if (parts.includes(`fateCompass`)) { - this.#animateCompassTo(); - }; - - if (parts.includes(`sandsOfFate`)) { - this.#animateSandsTo(); - }; - }; - - #animateCompassTo(newFate) { - if (newFate === this._currentFate) { return }; - - /** @type {HTMLElement|undefined} */ - const pointer = this.element.querySelector(`.compass-pointer`); - if (!pointer) { return }; - - newFate ??= game.settings.get(`ripcrypt`, `currentFate`); - - let distance = distanceBetweenFates(this._currentFate, newFate); - if (distance === 3) { distance = -1 }; - - this._rotation += distance * 90; - - pointer.style.setProperty(`transform`, `rotate(${this._rotation}deg)`); - this._currentFate = newFate; - }; - - #animateSandsTo(newSands) { - /** @type {HTMLElement|undefined} */ - const sands = this.element.querySelector(`.sands-value`); - if (!sands) { return }; - - newSands ??= game.settings.get(`ripcrypt`, `sandsOfFate`); - - sands.innerHTML = newSands; - this._sandsOfFate = newSands; - }; - // #endregion - - // #region Actions - /** @this {DelveDiceHUD} */ - static async #tourDelta(_event, element) { - const delta = parseInt(element.dataset.delta); - await this.sandsOfFateDelta(delta); - - switch (Math.sign(delta)) { - case -1: { - game.settings.set(`ripcrypt`, `currentFate`, nextFate(this._currentFate)); - break; - } - case 1: { - game.settings.set(`ripcrypt`, `currentFate`, previousFate(this._currentFate)); - break; - } - }; - }; - - /** @this {DelveDiceHUD} */ - static async #setFate(_event, element) { - const fate = element.dataset.toFate; - this.#animateCompassTo(fate); - game.settings.set(`ripcrypt`, `currentFate`, fate); - }; - - /** @this {DelveDiceHUD} */ - static async #setDifficulty(value) { - this._difficulty = value; - game.settings.set(`ripcrypt`, `dc`, value); - }; - // #endregion - - // #region Public API - async alertCrypticEvent() { - const alertType = game.settings.get(`ripcrypt`, `onCrypticEvent`); - if (alertType === `nothing`) { return }; - - if ([`both`, `notif`].includes(alertType)) { - ui.notifications.info( - 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/DicePool.mjs b/module/Apps/DicePool.mjs deleted file mode 100644 index 7418a3c..0000000 --- a/module/Apps/DicePool.mjs +++ /dev/null @@ -1,222 +0,0 @@ -import { filePath } from "../consts.mjs"; -import { GenericAppMixin } from "./GenericApp.mjs"; -import { localizer } from "../utils/Localizer.mjs"; -import { Logger } from "../utils/Logger.mjs"; - -const { Roll } = foundry.dice; -const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; - -export class DicePool extends GenericAppMixin(HandlebarsApplicationMixin(ApplicationV2)) { - // #region Options - static DEFAULT_OPTIONS = { - classes: [ - `ripcrypt--DicePool`, - ], - window: { - title: `Dice Pool`, - frame: true, - positioned: true, - resizable: false, - minimizable: true, - }, - position: { - width: `auto`, - height: `auto`, - }, - actions: { - diceCountDelta: this.#diceCountDelta, - targetDelta: this.#targetDelta, - edgeDelta: this.#edgeDelta, - dragDelta: this.#dragDelta, - roll: this.#roll, - }, - }; - - static PARTS = { - numberOfDice: { - template: filePath(`templates/Apps/DicePool/numberOfDice.hbs`), - }, - target: { - template: filePath(`templates/Apps/DicePool/target.hbs`), - }, - drag: { - template: filePath(`templates/Apps/DicePool/drag.hbs`), - }, - edge: { - template: filePath(`templates/Apps/DicePool/edge.hbs`), - }, - buttons: { - template: filePath(`templates/Apps/DicePool/buttons.hbs`), - }, - }; - // #endregion - - // #region Instance Data - _diceCount; - _target; - _drag; - _edge; - - constructor({ - diceCount = 1, - target, - drag = 0, edge = 0, - flavor = ``, - ...opts - } = {}) { - super(opts); - - this._drag = drag; - this._edge = edge; - this._flavor = flavor; - this._diceCount = diceCount; - this._target = target ?? game.settings.get(`ripcrypt`, `dc`) ?? 1; - }; - - get title() { - if (!this._flavor) { - return super.title; - } - return `${super.title}: ${this._flavor}`; - }; - // #endregion - - // #region Lifecycle - async _preparePartContext(partId, ctx, _opts) { - ctx = {}; - - switch (partId) { - case `numberOfDice`: { - await this._prepareNumberOfDice(ctx); - break; - }; - case `target`: { - await this._prepareTarget(ctx); - break; - }; - case `edge`: { - await this._prepareEdge(ctx); - break; - }; - case `drag`: { - await this._prepareDrag(ctx); - break; - }; - case `buttons`: { - break; - }; - } - - Logger.debug(`${partId} Context:`, ctx); - return ctx; - }; - - async _prepareNumberOfDice(ctx) { - ctx.numberOfDice = this._diceCount; - ctx.decrementDisabled = this._diceCount <= 1; - }; - - async _prepareTarget(ctx) { - ctx.target = this._target; - ctx.incrementDisabled = this._target >= 8; - ctx.decrementDisabled = this._target <= 1; - }; - - async _prepareEdge(ctx) { - ctx.edge = this._edge; - ctx.incrementDisabled = false; - ctx.decrementDisabled = this._edge <= 0; - }; - - async _prepareDrag(ctx) { - ctx.drag = this._drag; - ctx.incrementDisabled = false; - ctx.decrementDisabled = this._drag <= 0; - }; - // #endregion - - // #region Actions - static async #diceCountDelta(_event, element) { - const delta = parseInt(element.dataset.delta); - if (Number.isNaN(delta)) { - ui.notifications.error( - localizer(`RipCrypt.notifs.error.invalid-delta`, { name: `@RipCrypt.Apps.numberOfDice` }), - ); - return; - }; - - let newCount = this._diceCount + delta; - - if (newCount < 0) { - ui.notifications.warn( - localizer(`RipCrypt.notifs.warn.cannot-go-negative`, { name: `@RipCrypt.Apps.numberOfDice` }), - ); - }; - - this._diceCount = Math.max(newCount, 0); - this.render({ parts: [`numberOfDice`] }); - }; - - static async #targetDelta(_event, element) { - const delta = parseInt(element.dataset.delta); - if (Number.isNaN(delta)) { - ui.notifications.error( - localizer(`RipCrypt.notifs.error.invalid-delta`, { name: `@RipCrypt.Apps.rollTarget` }), - ); - return; - }; - - this._target += delta; - this.render({ parts: [`target`] }); - }; - - static async #edgeDelta(_event, element) { - const delta = parseInt(element.dataset.delta); - if (Number.isNaN(delta)) { - ui.notifications.error( - localizer(`RipCrypt.notifs.error.invalid-delta`, { name: `@RipCrypt.common.edge` }), - ); - return; - }; - - this._edge += delta; - this.render({ parts: [`edge`] }); - }; - - static async #dragDelta(_event, element) { - const delta = parseInt(element.dataset.delta); - if (Number.isNaN(delta)) { - ui.notifications.error( - localizer(`RipCrypt.notifs.error.invalid-delta`, { name: `@RipCrypt.common.drag` }), - ); - return; - }; - - this._drag += delta; - this.render({ parts: [`drag`] }); - }; - - static async #roll() { - let target = this._target; - target -= this._edge; - target += this._drag; - target = Math.max(target, 1); - - const formula = `${this._diceCount}d8rc${target}`; - Logger.debug(`Attempting to roll formula: ${formula}`); - - let flavor = this._flavor; - if (this._flavor) { - flavor += ` ` + localizer(`RipCrypt.Apps.difficulty`, { dc: this._target }); - } - - const roll = new Roll(formula); - await roll.evaluate(); - await roll.toMessage({ - speaker: ChatMessage.getSpeaker({ actor: this.actor }), - flavor, - }); - this.close(); - }; - // #endregion -}; diff --git a/module/Apps/GenericApp.mjs b/module/Apps/GenericApp.mjs index 0be30e4..8ebd20f 100644 --- a/module/Apps/GenericApp.mjs +++ b/module/Apps/GenericApp.mjs @@ -1,11 +1,10 @@ -import { createItemFromElement, deleteItemFromElement, editItemFromElement, updateForeignDocumentFromEvent } from "./utils.mjs"; -import { DicePool } from "./DicePool.mjs"; -import { RichEditor } from "./RichEditor.mjs"; -import { toBoolean } from "../consts.mjs"; +import { localizer } from "../utils/Localizer.mjs"; +import { Logger } from "../utils/Logger.mjs"; + +const { Roll } = foundry.dice; /** - * A mixin that takes the class from HandlebarsApplicationMixin and combines it - * with utility functions / data that is used across all RipCrypt applications + * A mixin that takes the class from HandlebarsApplicationMixin and */ export function GenericAppMixin(HandlebarsApp) { class GenericRipCryptApp extends HandlebarsApp { @@ -16,14 +15,7 @@ export function GenericAppMixin(HandlebarsApp) { `ripcrypt`, ], actions: { - roll: this.#rollDice, - createItem(_event, target) { // uses arrow-less function for "this" - const parent = this.document; - createItemFromElement(target, { parent }); - }, - editItem: (_event, target) => editItemFromElement(target), - deleteItem: (_event, target) => deleteItemFromElement(target), - openRichEditor: this.#openRichEditor, + roll: this.rollDice, }, }; @@ -32,57 +24,7 @@ export function GenericAppMixin(HandlebarsApp) { }; // #endregion - // #region Instance Data - /** @type {Map} */ - _popoverManagers = new Map(); - /** @type {Map} */ - _hookIDs = new Map(); - // #endregion - // #region Lifecycle - /** - * @override - * Making it so that if the app is already open, it's brought to - * top after being re-rendered as normal - */ - async render(options = {}, _options = {}) { - await super.render(options, _options); - const instance = foundry.applications.instances.get(this.id); - if (instance !== undefined && options.orBringToFront) { - instance.bringToFront(); - }; - }; - - /** @override */ - async _onRender(...args) { - await super._onRender(...args); - - /* - Rendering each of the popover managers associated with this app allows us - to have them be dynamic and update when their parent application is rerendered, - this could eventually be something we can move into the Document's apps - collection so Foundry auto-rerenders it, but because it isn't actually - associated with the Document (as it's dependendant on the Application), I - decided that it would be best to do my own handling for it. - */ - for (const manager of this._popoverManagers.values()) { - manager.render(); - }; - - /* - Foreign update listeners so that we can easily update items that may not - be this document itself, but are useful to be able to be edited from this - sheet. Primarily useful for editing the Actors' Item collection, or an Items' - ActiveEffect collection. - */ - this.element.querySelectorAll(`input[data-foreign-update-on]`).forEach(el => { - const events = el.dataset.foreignUpdateOn.split(`,`); - for (const event of events) { - el.addEventListener(event, updateForeignDocumentFromEvent); - }; - }); - }; - async _preparePartContext(partId, ctx, opts) { ctx = await super._preparePartContext(partId, ctx, opts); delete ctx.document; @@ -92,65 +34,32 @@ export function GenericAppMixin(HandlebarsApp) { ctx.meta.idp = this.document?.uuid ?? this.id; if (this.document) { ctx.meta.limited = this.document.limited; - ctx.meta.editable = this.isEditable || game.user.isGM; - ctx.meta.embedded = this.document.isEmbedded; - }; + ctx.meta.editable = ctx.editable; + } delete ctx.editable; return ctx; }; - - _tearDown(options) { - // Clear all popovers associated with the app - for (const manager of this._popoverManagers.values()) { - manager.destroy(); - }; - this._popoverManagers.clear(); - - // Remove any hooks added for this app - for (const [id, hook] of this._hookIDs.entries()) { - Hooks.off(hook, id); - }; - this._hookIDs.clear(); - - super._tearDown(options); - }; // #endregion // #region Actions /** @this {GenericRipCryptApp} */ - static async #rollDice(_event, target) { - const data = target.dataset; - const diceCount = parseInt(data.diceCount); - const flavor = data.flavor; + static async rollDice(_$e, el) { + const data = el.dataset; + const formula = data.formula; + Logger.debug(`Attempting to roll formula: ${formula}`); - const dp = new DicePool({ diceCount, flavor }); - dp.render({ force: true }); - }; + let flavor; + if (data.flavor) { + flavor = localizer(data.flavor); + } - /** @this {GenericRipCryptApp} */ - static async #openRichEditor(_event, target) { - const data = target.dataset; - const { - uuid, - path, - collaborative, - compact, - } = data; - - if (!uuid || !path) { - console.error(`Rich Editor requires a document uuid and path to edit`); - return; - }; - - const document = await fromUuid(uuid); - const app = new RichEditor({ - document, - path, - collaborative: toBoolean(collaborative), - compact: toBoolean(compact ), + const roll = new Roll(formula); + await roll.evaluate(); + await roll.toMessage({ + speaker: ChatMessage.getSpeaker({ actor: this.actor }), + flavor, }); - app.render({ force: true }); }; // #endregion }; diff --git a/module/Apps/ItemSheets/AllItemSheetV1.mjs b/module/Apps/ItemSheets/AllItemSheetV1.mjs deleted file mode 100644 index 0608fde..0000000 --- a/module/Apps/ItemSheets/AllItemSheetV1.mjs +++ /dev/null @@ -1,71 +0,0 @@ -import { filePath } from "../../consts.mjs"; -import { GenericAppMixin } from "../GenericApp.mjs"; -import { Logger } from "../../utils/Logger.mjs"; - -const { HandlebarsApplicationMixin } = foundry.applications.api; -const { ItemSheetV2 } = foundry.applications.sheets; - -export class AllItemSheetV1 extends GenericAppMixin(HandlebarsApplicationMixin(ItemSheetV2)) { - - // #region Options - static DEFAULT_OPTIONS = { - classes: [ - `ripcrypt--item`, - `ripcrypt--AllItemSheetV1`, - ], - position: { - width: `auto`, - height: `auto`, - }, - window: { - resizable: false, - }, - form: { - submitOnChange: true, - closeOnSubmit: false, - }, - }; - - static PARTS = { - content: { - template: filePath(`templates/Apps/AllItemSheetV1/content.hbs`), - }, - }; - // #endregion - - // #region Lifecycle - async _preparePartContext(partId, ctx, opts) { - ctx = await super._preparePartContext(partId, ctx, opts); - ctx.item = this.document; - - ctx.formFields = await this.document.system.getFormFields(ctx); - - Logger.debug(`Context:`, ctx); - return ctx; - }; - - 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(); - }; - }; - // #endregion - - // #region Actions - // #endregion -}; diff --git a/module/Apps/ItemSheets/ArmourSheet.mjs b/module/Apps/ItemSheets/ArmourSheet.mjs deleted file mode 100644 index 7570413..0000000 --- a/module/Apps/ItemSheets/ArmourSheet.mjs +++ /dev/null @@ -1,135 +0,0 @@ -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/RichEditor.mjs b/module/Apps/RichEditor.mjs deleted file mode 100644 index 2bd1bc4..0000000 --- a/module/Apps/RichEditor.mjs +++ /dev/null @@ -1,88 +0,0 @@ -/* -This Application is used by parts of the system to enable a better experience -while editing enriched text, because a lot of the spaces for text are really -small and are better served by a bigger text editor so that the controls are -more visible and doesn't cause as much overflow chaos. -*/ - -import { filePath } from "../consts.mjs"; - -const { HandlebarsApplicationMixin, DocumentSheetV2 } = foundry.applications.api; -const { hasProperty, getProperty } = foundry.utils; - -export class RichEditor extends HandlebarsApplicationMixin(DocumentSheetV2) { - // #region Options - static DEFAULT_OPTIONS = { - classes: [ - `ripcrypt`, - `ripcrypt--RichEditor`, - ], - window: { - title: `Text Editor`, - frame: true, - positioned: true, - resizable: false, - minimizable: true, - }, - position: { - width: `auto`, - height: `auto`, - }, - actions: {}, - form: { - submitOnChange: true, - closeOnSubmit: false, - }, - }; - - static PARTS = { - editor: { - template: filePath(`templates/Apps/RichEditor/content.hbs`), - root: true, - }, - }; - // #endregion - - // #region Instance Data - document; - path; - - constructor(opts) { - const { - document, - path, - compact = false, - collaborative = true, - } = opts; - - if (!hasProperty(document, path)) { - throw new Error(`Document provided to text editor must have the property specified by the path.`); - }; - - opts.sheetConfig = false; - super(opts); - - this.compact = compact; - this.collaborative = collaborative; - this.document = document; - this.path = path; - }; - // #endregion - - // #region Lifecycle - async _preparePartContext(partId, ctx, _opts) { - ctx = { - uuid: this.document.uuid, - editable: true, // this.isEditable - collaborative: this.collaborative, - compact: this.compact, - path: this.path, - }; - - const value = getProperty(this.document, this.path); - ctx.enriched = await TextEditor.enrichHTML(value); - ctx.raw = value; - return ctx; - }; - // #endregion -}; diff --git a/module/Apps/components/ArmourSummary.mjs b/module/Apps/components/ArmourSummary.mjs deleted file mode 100644 index 15ddf16..0000000 --- a/module/Apps/components/ArmourSummary.mjs +++ /dev/null @@ -1,56 +0,0 @@ -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/components/RipCryptBorder.mjs b/module/Apps/components/RipCryptBorder.mjs deleted file mode 100644 index f2722c1..0000000 --- a/module/Apps/components/RipCryptBorder.mjs +++ /dev/null @@ -1,55 +0,0 @@ -import { StyledShadowElement } from "./mixins/StyledShadowElement.mjs"; - -/** -Attributes: -*/ -export class RipCryptBorder extends StyledShadowElement(HTMLElement) { - static elementName = `rc-border`; - static formAssociated = false; - - /* Stuff for the mixin to use */ - static _stylePath = `css/components/rc-border.css`; - #container; - - _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 = `rc-border`; - - const titleContainer = document.createElement(`div`); - titleContainer.classList = `title`; - const titleSlot = document.createElement(`slot`); - titleSlot.innerHTML = `No Title`; - titleSlot.name = `title`; - titleContainer.appendChild(titleSlot.cloneNode(true)); - this.#container.appendChild(titleContainer.cloneNode(true)); - - const contentSlot = document.createElement(`slot`); - contentSlot.name = `content`; - this.#container.appendChild(contentSlot.cloneNode(true)); - - this._shadow.appendChild(this.#container); - - this._mounted = true; - }; - - disconnectedCallback() { - super.disconnectedCallback(); - if (!this._mounted) { return }; - this._mounted = false; - }; -}; diff --git a/module/Apps/components/svgLoader.mjs b/module/Apps/components/svgLoader.mjs deleted file mode 100644 index d9bf622..0000000 --- a/module/Apps/components/svgLoader.mjs +++ /dev/null @@ -1,11 +0,0 @@ -import { RipCryptIcon } from "./Icon.mjs"; - -/** -Attributes: -@property {string} name - The name of the icon, takes precedence over the path -@property {string} path - The path of the icon file -*/ -export class RipCryptSVGLoader extends RipCryptIcon { - static elementName = `rc-svg`; - static _stylePath = `css/components/svg-loader.css`; -}; diff --git a/module/Apps/components/Icon.mjs b/module/Apps/elements/Icon.mjs similarity index 94% rename from module/Apps/components/Icon.mjs rename to module/Apps/elements/Icon.mjs index 3a8e961..722ee36 100644 --- a/module/Apps/components/Icon.mjs +++ b/module/Apps/elements/Icon.mjs @@ -26,6 +26,7 @@ export class RipCryptIcon extends StyledShadowElement(HTMLElement) { constructor() { super(); + // this._shadow = this.attachShadow({ mode: `open`, delegatesFocus: true }); this.#container = document.createElement(`div`); this._shadow.appendChild(this.#container); @@ -96,7 +97,7 @@ export class RipCryptIcon extends StyledShadowElement(HTMLElement) { async #getIcon(path) { // Cache hit! if (this.constructor._cache.has(path)) { - Logger.debug(`Image ${path} cache hit`); + Logger.debug(`Icon ${path} cache hit`); return this.constructor._cache.get(path); }; @@ -110,7 +111,7 @@ export class RipCryptIcon extends StyledShadowElement(HTMLElement) { return; }; - Logger.debug(`Adding image ${path} to the cache`); + Logger.debug(`Adding icon ${path} to the cache`); const svg = this.#parseSVG(await r.text()); this.constructor._cache.set(path, svg); return svg; @@ -122,4 +123,4 @@ export class RipCryptIcon extends StyledShadowElement(HTMLElement) { temp.innerHTML = content; return temp.querySelector(`svg`); }; -}; +}; \ No newline at end of file diff --git a/module/Apps/components/_index.mjs b/module/Apps/elements/_index.mjs similarity index 73% rename from module/Apps/components/_index.mjs rename to module/Apps/elements/_index.mjs index 8400462..baaef94 100644 --- a/module/Apps/components/_index.mjs +++ b/module/Apps/elements/_index.mjs @@ -1,14 +1,8 @@ -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, ]; export function registerCustomComponents() { diff --git a/module/Apps/components/mixins/StyledShadowElement.mjs b/module/Apps/elements/mixins/StyledShadowElement.mjs similarity index 66% rename from module/Apps/components/mixins/StyledShadowElement.mjs rename to module/Apps/elements/mixins/StyledShadowElement.mjs index 37f81d1..c645111 100644 --- a/module/Apps/components/mixins/StyledShadowElement.mjs +++ b/module/Apps/elements/mixins/StyledShadowElement.mjs @@ -11,9 +11,9 @@ export function StyledShadowElement(Base) { /** * The stringified CSS to use - * @type {Map} + * @type {string} */ - static _styles = new Map(); + static _styles; /** * The HTML element of the stylesheet @@ -24,6 +24,12 @@ export function StyledShadowElement(Base) { /** @type {ShadowRoot} */ _shadow; + /** + * The hook ID for this element's CSS hot reload + * @type {number} + */ + #cssHmr; + constructor() { super(); @@ -43,23 +49,24 @@ export function StyledShadowElement(Base) { disconnectedCallback() { if (!this.#mounted) { return }; + if (this.#cssHmr != null) { + Hooks.off(`dd-hmr:css`, this.#cssHmr); + this.#cssHmr = null; + }; this.#mounted = false; }; _getStyles() { - // TODO: Cache the CSS content in a more sane way that doesn't break - const stylePath = this.constructor._stylePath; - if (this.constructor._styles.has(stylePath)) { - this._style.innerHTML = this.constructor._styles.get(stylePath); - } - else { - fetch(`./systems/${game.system.id}/templates/${stylePath}`) + if (this.constructor._styles) { + this._style.innerHTML = this.constructor._styles; + } else { + fetch(`./systems/${game.system.id}/templates/${this.constructor._stylePath}`) .then(r => r.text()) .then(t => { - this.constructor._styles.set(stylePath, t); + this.constructor._styles = t; this._style.innerHTML = t; }); } }; }; -}; +}; \ No newline at end of file diff --git a/module/Apps/popovers/AmmoTracker.mjs b/module/Apps/popovers/AmmoTracker.mjs deleted file mode 100644 index 458e783..0000000 --- a/module/Apps/popovers/AmmoTracker.mjs +++ /dev/null @@ -1,96 +0,0 @@ -import { filePath } from "../../consts.mjs"; -import { GenericPopoverMixin } from "./GenericPopoverMixin.mjs"; -import { ItemFlags } from "../../flags/item.mjs"; -import { localizer } from "../../utils/Localizer.mjs"; -import { Logger } from "../../utils/Logger.mjs"; - -const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; - -export class AmmoTracker extends GenericPopoverMixin(HandlebarsApplicationMixin(ApplicationV2)) { - // #region Options - static DEFAULT_OPTIONS = { - classes: [ - `ripcrypt`, - ], - window: { - title: `RipCrypt.app-titles.AmmoTracker`, - contentClasses: [ - `ripcrypt--AmmoTracker`, - ], - }, - actions: { - favourite: this.#favourite, - unfavourite: this.#unfavourite, - }, - }; - - static PARTS = { - ammoList: { - template: filePath(`templates/Apps/popovers/AmmoTracker/ammoList.hbs`), - }, - }; - // #endregion - - // #region Instance Data - _favouriteCount = 0; - // #endregion - - // #region Lifecycle - async _preparePartContext(partId, data) { - const ctx = { - meta: { idp: this.id }, - partId, - }; - - let favouriteCount = 0; - ctx.ammos = data.ammos.map(ammo => { - const favourite = ammo.getFlag(game.system.id, ItemFlags.FAVOURITE) ?? false; - if (favourite) { favouriteCount++ }; - - return { - ammo, - favourite, - }; - }); - - this._favouriteCount = favouriteCount; - ctx.atFavouriteLimit = favouriteCount >= 3; - return ctx; - }; - // #endregion - - // #region Actions - static async #favourite(_, el) { - const targetEl = el.closest(`[data-item-id]`); - if (!targetEl) { - Logger.warn(`Cannot find a parent element with data-item-id`); - return; - }; - - if (this._favouriteCount > 3) { - ui.notifications.error(localizer(`RipCrypt.notifs.error.at-favourite-limit`)); - return; - }; - - const data = targetEl.dataset; - const item = await fromUuid(data.itemId); - if (!item) { return }; - - item.setFlag(game.system.id, ItemFlags.FAVOURITE, true); - }; - - static async #unfavourite(_, el) { - const targetEl = el.closest(`[data-item-id]`); - if (!targetEl) { - Logger.warn(`Cannot find a parent element with data-item-id`); - return; - }; - - const data = targetEl.dataset; - const item = await fromUuid(data.itemId); - if (!item) { return }; - - item.unsetFlag(game.system.id, ItemFlags.FAVOURITE); - }; - // #endregion -}; diff --git a/module/Apps/popovers/GenericPopoverMixin.mjs b/module/Apps/popovers/GenericPopoverMixin.mjs deleted file mode 100644 index 271bb9a..0000000 --- a/module/Apps/popovers/GenericPopoverMixin.mjs +++ /dev/null @@ -1,188 +0,0 @@ -import { updateForeignDocumentFromEvent } from "../utils.mjs"; - -const { ApplicationV2 } = foundry.applications.api; - -/** - * This mixin provides the ability to designate an Application as a "popover", - * which means that it will spawn near the x/y coordinates provided it won't - * overflow the bounds of the screen. This also implements a _preparePartContext - * in order to allow the parent application passing new data into the popover - * whenever it rerenders; how the popover handles this data is up to the - * specific implementation. - */ -export function GenericPopoverMixin(HandlebarsApp) { - class GenericRipCryptPopover extends HandlebarsApp { - static DEFAULT_OPTIONS = { - id: `popover-{id}`, - classes: [ - `popover`, - ], - window: { - frame: false, - positioned: true, - resizable: false, - minimizable: false, - }, - actions: {}, - }; - - popover = {}; - constructor({ popover, ...options}) { - - // For when the caller doesn't provide anything, we want this to behave - // like a normal Application instance. - popover.framed ??= true; - popover.locked ??= false; - - if (popover.framed) { - options.window ??= {}; - options.window.frame = true; - options.window.minimizable = true; - } - - options.classes ??= []; - options.classes.push(popover.framed ? `framed` : `frameless`); - - super(options); - this.popover = popover; - }; - - toggleLock() { - this.popover.locked = !this.popover.locked; - this.classList.toggle(`locked`, this.popover.locked); - }; - - /** - * This render utility is intended in order to make the popovers able to be - * used in both framed and frameless mode, making sure that the content classes - * from the framed mode get shunted onto the frameless Application's root - * element. - */ - async _onFirstRender(...args) { - await super._onFirstRender(...args); - - const hasContentClasses = this.options?.window?.contentClasses?.length > 0; - if (!this.popover.framed && hasContentClasses) { - this.classList.add(...this.options.window.contentClasses); - }; - }; - - async _onRender(...args) { - await super._onRender(...args); - - /* - Foreign update listeners so that we can easily update items that may not - be this document itself, but are useful to be able to be edited from this - sheet. Primarily useful for editing the Actors' Item collection, or an Items' - ActiveEffect collection. - */ - this.element.querySelectorAll(`input[data-foreign-update-on]`).forEach(el => { - const events = el.dataset.foreignUpdateOn.split(`,`); - for (const event of events) { - el.addEventListener(event, updateForeignDocumentFromEvent); - }; - }); - }; - - async close(options = {}) { - // prevent locked popovers from being closed - if (this.popover.locked && !options.force) { return }; - - if (!this.popover.framed) { - options.animate = false; - }; - return super.close(options); - }; - - /** - * @override - * Custom implementation in order to make it show up approximately where I - * want it to when being created. - * - * Most of this implementation is identical to the ApplicationV2 - * implementation, the biggest difference is how targetLeft and targetTop - * are calculated. - */ - _updatePosition(position) { - if (!this.element) { return position }; - if (this.popover.framed) { return super._updatePosition(position) }; - - const el = this.element; - let {width, height, left, top, scale} = position; - scale ??= 1.0; - const computedStyle = getComputedStyle(el); - let minWidth = ApplicationV2.parseCSSDimension(computedStyle.minWidth, el.parentElement.offsetWidth) || 0; - let maxWidth = ApplicationV2.parseCSSDimension(computedStyle.maxWidth, el.parentElement.offsetWidth) || Infinity; - let minHeight = ApplicationV2.parseCSSDimension(computedStyle.minHeight, el.parentElement.offsetHeight) || 0; - let maxHeight = ApplicationV2.parseCSSDimension(computedStyle.maxHeight, el.parentElement.offsetHeight) || Infinity; - let bounds = el.getBoundingClientRect(); - const {clientWidth, clientHeight} = document.documentElement; - - // Explicit width - const autoWidth = width === `auto`; - if ( !autoWidth ) { - const targetWidth = Number(width || bounds.width); - minWidth = parseInt(minWidth) || 0; - maxWidth = parseInt(maxWidth) || (clientWidth / scale); - width = Math.clamp(targetWidth, minWidth, maxWidth); - } - - // Explicit height - const autoHeight = height === `auto`; - if ( !autoHeight ) { - const targetHeight = Number(height || bounds.height); - minHeight = parseInt(minHeight) || 0; - maxHeight = parseInt(maxHeight) || (clientHeight / scale); - height = Math.clamp(targetHeight, minHeight, maxHeight); - } - - // Implicit height - if ( autoHeight ) { - Object.assign(el.style, {width: `${width}px`, height: ``}); - bounds = el.getBoundingClientRect(); - height = bounds.height; - } - - // Implicit width - if ( autoWidth ) { - Object.assign(el.style, {height: `${height}px`, width: ``}); - bounds = el.getBoundingClientRect(); - width = bounds.width; - } - - // Left Offset - const scaledWidth = width * scale; - const targetLeft = left ?? (this.popover.x - Math.floor( scaledWidth / 2 )); - const maxLeft = Math.max(clientWidth - scaledWidth, 0); - left = Math.clamp(targetLeft, 0, maxLeft); - - // Top Offset - const scaledHeight = height * scale; - const targetTop = top ?? (this.popover.y - scaledHeight); - const maxTop = Math.max(clientHeight - scaledHeight, 0); - top = Math.clamp(targetTop, 0, maxTop); - - // Scale - scale ??= 1.0; - return { - width: autoWidth ? `auto` : width, - height: autoHeight ? `auto` : height, - left, - top, - scale, - }; - }; - - /** - * This is here in order allow things that are not this Application - * to provide / augment the context data for the lifecycle of the app. - */ - async _prepareContext(_partId, _context, options) { - const context = {}; - Hooks.callAll(`prepare${this.constructor.name}Context`, context, options); - Hooks.callAll(`prepare${this.popover.managerId}Context`, context, options); - return context; - }; - }; - return GenericRipCryptPopover; -}; diff --git a/module/Apps/sidebar/CombatTracker.mjs b/module/Apps/sidebar/CombatTracker.mjs deleted file mode 100644 index d976867..0000000 --- a/module/Apps/sidebar/CombatTracker.mjs +++ /dev/null @@ -1,89 +0,0 @@ -const { CombatTracker } = foundry.applications.sidebar.tabs; - -function createButtonInnerHTML() { - const whoFirst = game.settings.get(`ripcrypt`, `whoFirst`); - let icon = `evil`; - let ariaLabel = `Geists go first, click to make heroes go first`; - - if (whoFirst === `friendly`) { - icon = `hero`; - ariaLabel = `Heroes go first, click to make geists go first`; - }; - - return ``; -}; - -function createButtonTooltip() { - const whoFirst = game.settings.get(`ripcrypt`, `whoFirst`); - if (whoFirst === `friendly`) { - return `Heroes currently go first`; - }; - return `Geists currently go first`; -}; - -export class RipCryptCombatTracker extends CombatTracker { - - static DEFAULT_OPTIONS = { - actions: { - toggleFirst: this.#toggleFirst, - }, - }; - - /** - * Changes the way the combat tracker renders combatant rows to account for - * multiple combatants being in the same combat "group", thus all going at the - * same time. - * - * @override - */ - async _prepareTurnContext(combat, combatant, index) { - const turn = await super._prepareTurnContext(combat, combatant, index); - - turn.hasDecimals = true; - turn.initiative = combatant.dynamicInitiative; - - const groupKey = combatant?.groupKey; - if (groupKey && combat.started) { - turn.active ||= combat.combatant?.groupKey === groupKey; - if (turn.active && !turn.css.includes(`active`)) { - turn.css += ` active`; - }; - }; - - return turn; - }; - - async _onRender(...args) { - await super._onRender(...args); - - const spacer = document.createElement(`div`); - spacer.classList.add(`spacer`); - - const button = document.createElement(`button`); - button.classList.add(`inline-control`, `combat-control`, `icon`); - button.type = `button`; - button.dataset.tooltip = createButtonTooltip(); - button.dataset.action = `toggleFirst`; - button.innerHTML = createButtonInnerHTML(); - button.disabled = !game.user.isGM; - - // Purge the combat controls that I don't want to exist because they don't - // make sense in the system. - this.element?.querySelector(`[data-action="rollNPC"]`)?.replaceWith(spacer.cloneNode(true)); - this.element?.querySelector(`[data-action="rollAll"]`)?.replaceWith(button.cloneNode(true)); - }; - - static async #toggleFirst(_event, element) { - game.tooltip.deactivate(); - const whoFirst = game.settings.get(`ripcrypt`, `whoFirst`); - const otherFirst = whoFirst === `friendly` ? `hostile` : `friendly`; - await game.settings.set(`ripcrypt`, `whoFirst`, otherFirst); - element.innerHTML = createButtonInnerHTML(); - element.dataset.tooltip = createButtonTooltip(); - game.tooltip.activate(element); - }; -}; diff --git a/module/Apps/utils.mjs b/module/Apps/utils.mjs deleted file mode 100644 index 47f8f01..0000000 --- a/module/Apps/utils.mjs +++ /dev/null @@ -1,65 +0,0 @@ -/* -This file contains utilities used by Applications in order to be DRYer -*/ - -/** - * @param {HTMLElement} target The element to operate on - */ -export async function createItemFromElement(target, { parent } = {}) { - const data = target.dataset; - const types = data.itemTypes?.split(`,`); - const type = data.defaultItemType; - await Item.createDialog( - { type }, - { parent, showEquipPrompt: false }, - { - types, - folders: [], - }, - ); -}; - -/** - * @param {HTMLElement} target The element to operate on - */ -export async function editItemFromElement(target) { - const itemEl = target.closest(`[data-item-id]`); - if (!itemEl) { return }; - const itemId = itemEl.dataset.itemId; - if (!itemId) { return }; - const item = await fromUuid(itemId); - item.sheet.render({ force: true, orBringToFront: true }); -}; - -/** - * @param {HTMLElement} target The element to operate on - */ -export async function deleteItemFromElement(target) { - const itemEl = target.closest(`[data-item-id]`); - if (!itemEl) { return }; - const itemId = itemEl.dataset.itemId; - if (!itemId) { return }; - const item = await fromUuid(itemId); - item.deleteDialog(); -}; - -/** - * Updates a document using the UUID, expects there to be the following - * dataset attributes: - * - "data-foreign-uuid" : The UUID of the document to update - * - "data-foreign-name" : The dot-separated path of the value to update - * - * @param {Event} event - */ -export async function updateForeignDocumentFromEvent(event) { - const target = event.currentTarget; - const data = target.dataset; - const document = await fromUuid(data.foreignUuid); - - let value = target.value; - switch (target.type) { - case `checkbox`: value = target.checked; break; - }; - - await document?.update({ [data.foreignName]: value }); -}; diff --git a/module/api.mjs b/module/api.mjs deleted file mode 100644 index 4938519..0000000 --- a/module/api.mjs +++ /dev/null @@ -1,43 +0,0 @@ -// App imports -import { AmmoTracker } from "./Apps/popovers/AmmoTracker.mjs"; -import { CombinedHeroSheet } from "./Apps/ActorSheets/CombinedHeroSheet.mjs"; -import { DicePool } from "./Apps/DicePool.mjs"; -import { RichEditor } from "./Apps/RichEditor.mjs"; -import { SkillsCardV1 } from "./Apps/ActorSheets/SkillsCardV1.mjs"; -import { StatsCardV1 } from "./Apps/ActorSheets/StatsCardV1.mjs"; - -// Util imports -import { distanceBetweenFates, nextFate, previousFate } from "./utils/fates.mjs"; -import { documentSorter } from "./consts.mjs"; -import { rankToInteger } from "./utils/rank.mjs"; - -// Misc Imports -import { ItemFlags } from "./flags/item.mjs"; - -const { deepFreeze } = foundry.utils; - -Object.defineProperty( - globalThis, - `ripcrypt`, - { - value: deepFreeze({ - Apps: { - AmmoTracker, - DicePool, - CombinedHeroSheet, - StatsCardV1, - SkillsCardV1, - RichEditor, - }, - utils: { - documentSorter, - distanceBetweenFates, - nextFate, - previousFate, - rankToInteger, - }, - ItemFlags, - }), - writable: false, - }, -); diff --git a/module/consts.mjs b/module/consts.mjs index ee88a31..dc5d000 100644 --- a/module/consts.mjs +++ b/module/consts.mjs @@ -1,5 +1,3 @@ -const { getType } = foundry.utils; - // MARK: filePath export function filePath(path) { if (path.startsWith(`/`)) { @@ -7,63 +5,3 @@ export function filePath(path) { }; return `systems/ripcrypt/${path}`; }; - -// MARK: toBoolean -/** - * Converts a value into a boolean based on the type of the value provided - * - * @param {any} val The value to convert - */ -export function toBoolean(val) { - switch (getType(val)) { - case `string`: { - return val === `true`; - }; - case `number`: { - return val === 1; - }; - }; - return Boolean(val); -}; - -// MARK: documentSorter -/** - * @typedef {Object} Sortable - * @property {integer} sort - * @property {string} name - */ - -/** - * Compares two Sortable documents in order to determine ordering - * @param {Sortable} a - * @param {Sortable} b - * @returns An integer dictating which order the two documents should be sorted in - */ -export function documentSorter(a, b) { - if (!a && !b) { - return 0; - } - else if (!a) { - return 1; - } - else if (!b) { - return -1; - }; - - const sortDelta = b.sort - a.sort; - if (sortDelta !== 0) { - return sortDelta; - }; - return Math.sign(a.name.localeCompare(b.name)); -}; - -// MARK: getTooltipDelay -/** - * Retrieves the configured minimum delay between the user hovering an element - * and a tooltip showing up. Used for the pseudo-tooltip Applications that I use. - * - * @returns The number of milliseconds for the timeout - */ -export function getTooltipDelay() { - return game.tooltip.constructor.TOOLTIP_ACTIVATION_MS; -}; diff --git a/module/data/Actor/Entity.mjs b/module/data/Actor/Entity.mjs deleted file mode 100644 index 89f2b7f..0000000 --- a/module/data/Actor/Entity.mjs +++ /dev/null @@ -1,201 +0,0 @@ -import { derivedMaximumBar } from "../helpers.mjs"; -import { gameTerms } from "../../gameTerms.mjs"; -import { rankToInteger } from "../../utils/rank.mjs"; -import { sumReduce } from "../../utils/sumReduce.mjs"; - -const { fields } = foundry.data; - -export class EntityData extends foundry.abstract.TypeDataModel { - - // MARK: Token Attrs - static get trackableAttributes() { - return { - bar: [ - `guts`, - ], - value: [ - `ability.grit`, - `ability.gait`, - `ability.grip`, - `ability.glim`, - `level.glory`, - `level.step`, - `level.rank`, - `coin.gold`, - `coin.silver`, - `coin.copper`, - ], - }; - }; - - // MARK: Schema - static defineSchema() { - return { - ability: new fields.SchemaField({ - grit: new fields.NumberField({ - min: 0, - initial: 1, - integer: true, - required: true, - nullable: false, - }), - gait: new fields.NumberField({ - min: 0, - initial: 1, - integer: true, - required: true, - nullable: false, - }), - grip: new fields.NumberField({ - min: 0, - initial: 1, - integer: true, - required: true, - nullable: false, - }), - glim: new fields.NumberField({ - min: 0, - initial: 1, - integer: true, - required: true, - nullable: false, - }), - }), - guts: derivedMaximumBar(0, 5), - coin: new fields.SchemaField({ - gold: new fields.NumberField({ - initial: 5, - integer: true, - required: true, - nullable: false, - }), - silver: new fields.NumberField({ - initial: 0, - integer: true, - required: true, - nullable: false, - }), - copper: new fields.NumberField({ - initial: 0, - integer: true, - required: true, - nullable: false, - }), - }), - fate: new fields.StringField({ - initial: ``, - blank: true, - trim: true, - nullable: false, - choices: () => { - return Object.values(gameTerms.FatePath).concat(``); - }, - }), - level: new fields.SchemaField({ - glory: new fields.NumberField({ - min: 0, - initial: 0, - integer: true, - required: true, - nullable: false, - }), - step: new fields.NumberField({ - min: 1, - initial: 1, - max: 3, - integer: true, - required: true, - nullable: false, - }), - rank: new fields.StringField({ - initial: gameTerms.Rank.NOVICE, - required: true, - nullable: false, - blank: false, - trim: true, - choices: Object.values(gameTerms.Rank), - }), - }), - }; - }; - - // MARK: Base Data - prepareBaseData() { - super.prepareBaseData(); - - // Calculate the person's base Crafting aura - const rank = rankToInteger(this.level.rank); - this.aura = { - normal: ( rank + 1 ) * 2, - heavy: ( rank + 2 ) * 2, - }; - - this.guts.max = 0; - - // The limitations imposed on things like inventory spaces and equipped - // weapon count - this.limit = { - weapons: 4, - equipment: 12, - skills: 4, - }; - }; - - // MARK: Derived Data - prepareDerivedData() { - super.prepareDerivedData(); - - this.guts.max += Object.values(this.ability).reduce(sumReduce); - - // Movement speeds - this.speed = { - move: this.ability.gait + 3, - run: (this.ability.gait + 3) * 2, - }; - }; - - // #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( - Object.values(gameTerms.Anatomy).map(v => [v, null]), - ); - for (const armour of armours) { - if (!armour.system.equipped) { continue }; - for (const locationTag of [...armour.system.location.values()]) { - const location = locationTag.toLowerCase(); - slots[location] = armour; - }; - }; - return slots; - }; - - get equippedShield() { - const shields = this.parent.itemTypes.shield; - return shields.find(item => item.system.equipped); - }; - - get defense() { - const defenses = {}; - const armour = this.equippedArmour; - for (const slot in armour) { - defenses[slot] = armour[slot]?.system.protection ?? 0; - }; - - const shield = this.equippedShield; - if (shield) { - for (const location of [...shield.system.location.values()]) { - const slot = location.toLowerCase(); - defenses[slot] += shield.system.protection; - }; - }; - - return defenses; - }; - // #endregion -}; diff --git a/module/data/Actor/Geist.mjs b/module/data/Actor/Geist.mjs deleted file mode 100644 index 440392a..0000000 --- a/module/data/Actor/Geist.mjs +++ /dev/null @@ -1,3 +0,0 @@ -import { EntityData } from "./Entity.mjs"; - -export class GeistData extends EntityData {}; diff --git a/module/data/Actor/Hero.mjs b/module/data/Actor/Hero.mjs index 6e6c364..b38d26b 100644 --- a/module/data/Actor/Hero.mjs +++ b/module/data/Actor/Hero.mjs @@ -1,3 +1,150 @@ -import { EntityData } from "./Entity.mjs"; +import { gameTerms } from "../../gameTerms.mjs"; +import { sumReduce } from "../../utils/sumReduce.mjs"; -export class HeroData extends EntityData {}; +const { fields } = foundry.data; + +export class HeroData extends foundry.abstract.TypeDataModel { + + // MARK: Token Attrs + static get trackableAttributes() { + return { + bar: [ + `guts`, + ], + value: [ + `ability.grit`, + `ability.gait`, + `ability.grip`, + `ability.glim`, + `level.glory`, + `level.step`, + `level.rank`, + ], + }; + }; + + // MARK: Schema + static defineSchema() { + return { + ability: new fields.SchemaField({ + grit: new fields.NumberField({ + min: 0, + initial: 1, + integer: true, + required: true, + nullable: false, + }), + gait: new fields.NumberField({ + min: 0, + initial: 1, + integer: true, + required: true, + nullable: false, + }), + grip: new fields.NumberField({ + min: 0, + initial: 1, + integer: true, + required: true, + nullable: false, + }), + glim: new fields.NumberField({ + min: 0, + initial: 1, + integer: true, + required: true, + nullable: false, + }), + }), + guts: new fields.SchemaField({ + value: new fields.NumberField({ + min: 0, + initial: 5, + integer: true, + nullable: false, + }), + }), + coin: new fields.SchemaField({ + gold: new fields.NumberField({ + initial: 5, + integer: true, + required: true, + nullable: false, + }), + silver: new fields.NumberField({ + initial: 0, + integer: true, + required: true, + nullable: false, + }), + copper: new fields.NumberField({ + initial: 0, + integer: true, + required: true, + nullable: false, + }), + }), + fate: new fields.StringField({ + initial: ``, + blank: true, + trim: true, + nullable: false, + choices: () => { + return gameTerms.FatePath.concat(``); + }, + }), + level: new fields.SchemaField({ + glory: new fields.NumberField({ + min: 0, + initial: 0, + integer: true, + required: true, + nullable: false, + }), + step: new fields.NumberField({ + min: 1, + initial: 1, + max: 3, + integer: true, + required: true, + nullable: false, + }), + rank: new fields.StringField({ + initial: gameTerms.Rank.NOVICE, + required: true, + nullable: false, + blank: false, + trim: true, + choices: Object.values(gameTerms.Rank), + }), + }), + }; + }; + + // MARK: Base Data + prepareBaseData() { + super.prepareBaseData(); + + this.guts.max = 0; + + // The limitations imposed on things like inventory spaces and equipped + // weapon count + this.limit = { + weapons: 4, + equipment: 12, + }; + }; + + // MARK: Derived Data + prepareDerivedData() { + super.prepareDerivedData(); + + this.guts.max += Object.values(this.ability).reduce(sumReduce); + + // Movement speeds + this.speed = { + move: this.ability.gait + 3, + run: (this.ability.gait + 3) * 2, + }; + }; +}; diff --git a/module/data/Item/Ammo.mjs b/module/data/Item/Ammo.mjs deleted file mode 100644 index 0493eb1..0000000 --- a/module/data/Item/Ammo.mjs +++ /dev/null @@ -1,59 +0,0 @@ -import { CommonItemData } from "./Common.mjs"; -import { gameTerms } from "../../gameTerms.mjs"; - -export class AmmoData extends CommonItemData { - // MARK: Base Data - prepareBaseData() { - super.prepareBaseData(); - }; - - // MARK: Derived Data - prepareDerivedData() { - super.prepareDerivedData(); - }; - - // #region Getters - // #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, - }, - ]; - return fields; - }; - // #endregion -}; diff --git a/module/data/Item/Armour.mjs b/module/data/Item/Armour.mjs deleted file mode 100644 index f2a1b0a..0000000 --- a/module/data/Item/Armour.mjs +++ /dev/null @@ -1,118 +0,0 @@ -import { CommonItemData } from "./Common.mjs"; -import { gameTerms } from "../../gameTerms.mjs"; -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; - -/** Used for Armour and Shields */ -export class ArmourData extends CommonItemData { - // #region Schema - static defineSchema() { - return { - ...super.defineSchema(), - protection: requiredInteger({ min: 0, initial: 1 }), - location: new fields.SetField( - new fields.StringField({ - blank: false, - trim: true, - nullable: false, - required: true, - options: Object.values(gameTerms.Anatomy), - }), - { - nullable: false, - initial: [], - }, - ), - equipped: new fields.BooleanField({ - initial: false, - nullable: false, - }), - weight: new fields.StringField({ - blank: false, - nullable: true, - initial: null, - options: Object.values(gameTerms.WeightRatings), - }), - }; - }; - // #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) { - 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 (getProperty(diff, `system.equipped`) && !this._canEquip()) { - ui.notifications.error( - localizer( - `RipCrypt.notifs.error.cannot-equip`, - { itemType: `@TYPES.Item.${this.parent.type}` }, - ), - { console: 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 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; - }; - - if (this.location.size === 0) { - Logger.error(`Unable to equip an item without any locations`); - return false; - }; - - const slots = parent.parent.system.equippedArmour ?? {}; - - for (const locationTag of this.location) { - if (slots[locationTag.toLowerCase()] != null) { - Logger.error(`Unable to equip multiple items in the same slot`); - return false; - }; - }; - return true; - }; - - get locationString() { - return [...this.location].join(`, `); - }; - // #endregion Helpers -}; diff --git a/module/data/Item/Common.mjs b/module/data/Item/Common.mjs deleted file mode 100644 index bf37c0e..0000000 --- a/module/data/Item/Common.mjs +++ /dev/null @@ -1,34 +0,0 @@ -import { optionalInteger, requiredInteger } from "../helpers.mjs"; -import { gameTerms } from "../../gameTerms.mjs"; - -const { fields } = foundry.data; - -export class CommonItemData extends foundry.abstract.TypeDataModel { - // MARK: Schema - static defineSchema() { - return { - quantity: requiredInteger({ min: 0, initial: 1 }), - access: new fields.StringField({ - blank: true, - nullable: false, - trim: true, - choices: gameTerms.Access, - }), - cost: new fields.SchemaField({ - gold: optionalInteger(), - silver: optionalInteger(), - copper: optionalInteger(), - }), - }; - }; - - // MARK: Base Data - prepareBaseData() { - super.prepareBaseData(); - }; - - // MARK: Derived Data - prepareDerivedData() { - super.prepareDerivedData(); - }; -}; diff --git a/module/data/Item/Craft.mjs b/module/data/Item/Craft.mjs deleted file mode 100644 index 23aa9ba..0000000 --- a/module/data/Item/Craft.mjs +++ /dev/null @@ -1,78 +0,0 @@ -import { gameTerms } from "../../gameTerms.mjs"; -import { SkillData } from "./Skill.mjs"; - -const { fields } = foundry.data; - -export class CraftData extends SkillData { - // MARK: Schema - static defineSchema() { - const schema = super.defineSchema(); - delete schema.ability; - - schema.aspect = new fields.StringField({ - initial: gameTerms.Aspects.FLECT, - blank: true, - trim: true, - nullable: false, - required: true, - choices: () => Object.values(gameTerms.Aspects), - }); - - return schema; - }; - - // MARK: Base Data - prepareBaseData() { - super.prepareBaseData(); - }; - - // MARK: Derived Data - prepareDerivedData() { - super.prepareDerivedData(); - }; - - // #region Getters - // #endregion - - // #region Sheet Data - async getFormFields(_ctx) { - const fields = [ - { - id: `fate-path`, - type: `dropdown`, - label: `RipCrypt.common.aspect`, - path: `system.aspect`, - value: this.aspect, - options: Object.values(gameTerms.Aspects).map(aspect => ({ - label: `RipCrypt.common.aspectNames.${aspect}`, - value: aspect, - })), - }, - { - id: `description`, - type: `prosemirror`, - label: `RipCrypt.common.description`, - path: `system.description`, - uuid: this.parent.uuid, - value: await TextEditor.enrichHTML(this.description), - collaborative: false, - }, - { - type: `group`, - title: `RipCrypt.common.advances`, - paddingTop: `20px`, - fields: Object.values(gameTerms.Rank).map(rank => { - return { - id: `advance-${rank}`, - type: `text`, - label: `RipCrypt.common.rankNames.${rank}`, - path: `system.advances.${rank}`, - value: this.advances[rank] ?? ``, - }; - }), - }, - ]; - return fields; - }; - // #endregion -}; diff --git a/module/data/Item/Good.mjs b/module/data/Item/Good.mjs deleted file mode 100644 index 9af246b..0000000 --- a/module/data/Item/Good.mjs +++ /dev/null @@ -1,83 +0,0 @@ -import { CommonItemData } from "./Common.mjs"; -import { gameTerms } from "../../gameTerms.mjs"; - -const { fields } = foundry.data; - -export class GoodData extends CommonItemData { - // MARK: Schema - static defineSchema() { - const schema = super.defineSchema(); - - schema.description = new fields.HTMLField({ - blank: true, - nullable: false, - trim: true, - }); - - return schema; - }; - - // MARK: Base Data - prepareBaseData() { - super.prepareBaseData(); - }; - - // MARK: Derived Data - prepareDerivedData() { - super.prepareDerivedData(); - }; - - // #region Getters - // #endregion - - // #region Sheet Data - async 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: `description`, - type: `prosemirror`, - label: `RipCrypt.common.description`, - path: `system.description`, - uuid: this.parent.uuid, - value: await TextEditor.enrichHTML(this.description), - collaborative: false, - }, - ]; - return fields; - }; - // #endregion -}; diff --git a/module/data/Item/Shield.mjs b/module/data/Item/Shield.mjs deleted file mode 100644 index aed37b7..0000000 --- a/module/data/Item/Shield.mjs +++ /dev/null @@ -1,19 +0,0 @@ -import { ArmourData } from "./Armour.mjs"; -import { Logger } from "../../utils/Logger.mjs"; - -export class ShieldData extends ArmourData { - _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 shield = parent.parent.system.equippedShield; - if (shield) { - Logger.error(`Unable to equip multiple shields`); - return false; - }; - return true; - }; -}; diff --git a/module/data/Item/Skill.mjs b/module/data/Item/Skill.mjs deleted file mode 100644 index 520a344..0000000 --- a/module/data/Item/Skill.mjs +++ /dev/null @@ -1,91 +0,0 @@ -import { gameTerms } from "../../gameTerms.mjs"; - -const { fields } = foundry.data; - -export class SkillData extends foundry.abstract.TypeDataModel { - // MARK: Schema - static defineSchema() { - const schema = { - ability: new fields.StringField({ - initial: gameTerms.Abilities.GRIT, - blank: true, - trim: true, - nullable: false, - required: true, - choices: () => Object.values(gameTerms.Abilities), - }), - description: new fields.HTMLField({ - blank: true, - nullable: false, - trim: true, - }), - }; - - const advances = {}; - for (const rank of Object.values(gameTerms.Rank)) { - advances[rank] = new fields.StringField({ - blank: false, - nullable: true, - initial: null, - }); - }; - schema.advances = new fields.SchemaField(advances); - - return schema; - }; - - // MARK: Base Data - prepareBaseData() { - super.prepareBaseData(); - }; - - // MARK: Derived Data - prepareDerivedData() { - super.prepareDerivedData(); - }; - - // #region Getters - // #endregion - - // #region Sheet Data - async getFormFields(_ctx) { - const fields = [ - { - id: `fate-path`, - type: `dropdown`, - label: `RipCrypt.common.ability`, - path: `system.ability`, - value: this.ability, - options: Object.values(gameTerms.Abilities).map(ability => ({ - label: `RipCrypt.common.abilities.${ability}`, - value: ability, - })), - }, - { - id: `description`, - type: `prosemirror`, - label: `RipCrypt.common.description`, - path: `system.description`, - uuid: this.parent.uuid, - value: await TextEditor.enrichHTML(this.description), - collaborative: false, - }, - { - type: `group`, - title: `RipCrypt.common.advances`, - paddingTop: `20px`, - fields: Object.values(gameTerms.Rank).map(rank => { - return { - id: `advance-${rank}`, - type: `text`, - label: `RipCrypt.common.rankNames.${rank}`, - path: `system.advances.${rank}`, - value: this.advances[rank] ?? ``, - }; - }), - }, - ]; - return fields; - }; - // #endregion -}; diff --git a/module/data/Item/Weapon.mjs b/module/data/Item/Weapon.mjs index ec35f29..2e42e35 100644 --- a/module/data/Item/Weapon.mjs +++ b/module/data/Item/Weapon.mjs @@ -1,18 +1,12 @@ 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; -export class WeaponData extends CommonItemData { - // #region Schema +export class WeaponData extends foundry.abstract.TypeDataModel { + // MARK: Schema static defineSchema() { return { - ...super.defineSchema(), traits: new fields.SetField( new fields.StringField({ blank: false, @@ -30,233 +24,35 @@ export class WeaponData extends CommonItemData { }), damage: requiredInteger({ min: 0, initial: 0 }), wear: barAttribute(0, 0, 4), - equipped: new fields.BooleanField({ - initial: false, - required: true, + access: new fields.StringField({ + blank: true, nullable: false, - }), - weight: new fields.StringField({ - blank: false, - nullable: true, - initial: null, - options: Object.values(gameTerms.WeightRatings), + trim: true, + choices: gameTerms.Access, }), }; }; - // #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 }); - }; - }; + // MARK: Base Data + prepareBaseData() { + super.prepareBaseData(); }; - /** - * - * @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 (getProperty(diff, `system.equipped`) && !this._canEquip()) { - ui.notifications.error(localizer( - `RipCrypt.notifs.error.cannot-equip`, - { itemType: `@TYPES.Item.${this.parent.type}` }, - )); - - // 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 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; + // MARK: Derived Data + prepareDerivedData() { + super.prepareDerivedData(); }; + // #region Getters get traitString() { return [...this.traits].join(`, `); - }; + } get rangeString() { if (this.range.short && this.range.long) { return `${this.range.short} / ${this.range.long}`; }; return String(this.range.short ?? this.range.long ?? ``); - }; - // #endregion Helpers - - // #region Sheet Data - async 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: `traits`, - type: `string-set`, - label: `RipCrypt.common.traits`, - placeholder: `RipCrypt.Apps.traits-placeholder`, - path: `system.traits`, - value: this.traitString, - }, - ]; - - // Add the range inputs depending on whether the user wants condensed range - // or not. - if (game.settings.get(`ripcrypt`, `condensedRange`)) { - fields.push({ - type: `bar`, - label: `RipCrypt.common.range`, - value: { - label: `RipCrypt.Apps.short-range`, - path: `system.range.short`, - value: this.range.short, - }, - max: { - label: `RipCrypt.Apps.long-range`, - path: `system.range.long`, - value: this.range.long, - }, - }); - } - else { - fields.push({ - id: `short-range`, - type: `integer`, - label: `RipCrypt.Apps.short-range`, - path: `system.range.short`, - value: this.range.short ?? ``, - min: 0, - }, - { - id: `long-range`, - type: `integer`, - label: `RipCrypt.Apps.long-range`, - path: `system.range.long`, - value: this.range.long ?? ``, - min: 0, - }); - }; - - fields.push( - { - id: `damage`, - type: `integer`, - label: `RipCrypt.common.damage`, - path: `system.damage`, - value: this.damage, - min: 0, - }, - { - type: `bar`, - label: `RipCrypt.common.wear`, - value: { - label: `RipCrypt.Apps.current-wear`, - path: `system.wear.value`, - value: this.wear.value, - min: 0, max: this.wear.max, - }, - max: { - label: `RipCrypt.Apps.max-wear`, - path: `system.wear.max`, - value: this.wear.max, - min: 0, - }, - }, - ); - - if (this.parent.isEmbedded) { - fields.push({ - id: `equipped`, - type: `boolean`, - label: `RipCrypt.common.equipped`, - value: this.equipped, - path: `system.equipped`, - }); - }; - - return fields; - }; - // #endregion Sheet Data + } + // #endregion }; diff --git a/module/data/helpers.mjs b/module/data/helpers.mjs index e7c705f..2321503 100644 --- a/module/data/helpers.mjs +++ b/module/data/helpers.mjs @@ -19,17 +19,6 @@ export function barAttribute(min, initial, max = undefined) { }); }; -export function derivedMaximumBar(min, initial) { - return new fields.SchemaField({ - value: new fields.NumberField({ - min, - initial, - integer: true, - nullable: false, - }), - }); -}; - export function optionalInteger({min, initial = null, max} = {}) { return new fields.NumberField({ min, diff --git a/module/dice/CryptDie.mjs b/module/dice/CryptDie.mjs index 4da7ce7..9a573a2 100644 --- a/module/dice/CryptDie.mjs +++ b/module/dice/CryptDie.mjs @@ -26,8 +26,7 @@ export class CryptDie extends Die { }; /* - Handles "Crypting" rolls, which is a single explosion on 1's which if it - results in a second 1, causes the roll to "crypt" + Handles "Crypting" rolls, which is a single explosion that allows */ if (!this.ripCryptState) { await this.explode(`xo=1`, { recursive: false }); @@ -38,8 +37,7 @@ export class CryptDie extends Die { if (almostCrypted) { this.ripCryptState = `crypted`; break; - } - else { + } else { almostCrypted = true; } } diff --git a/module/documents/chatMessage/CryptRollMessage.mjs b/module/documents/chatMessage/CryptRollMessage.mjs new file mode 100644 index 0000000..7b0efc8 --- /dev/null +++ b/module/documents/chatMessage/CryptRollMessage.mjs @@ -0,0 +1,11 @@ +import { filePath } from "../../consts.mjs"; + +export class CryptRollMessage extends ChatMessage { + static get template() { + switch (this.type) { + case `roll`: + return filePath(`templates/chat/roll.hbs`); + } + return super.template; + }; +}; diff --git a/module/documents/combat.mjs b/module/documents/combat.mjs deleted file mode 100644 index f2aeb4b..0000000 --- a/module/documents/combat.mjs +++ /dev/null @@ -1,141 +0,0 @@ -/* -Resources: -- Combat : https://github.com/foundryvtt/dnd5e/blob/4.3.x/module/documents/combat.mjs -- Combatant : https://github.com/foundryvtt/dnd5e/blob/4.3.x/module/documents/combatant.mjs -- CombatTracker : https://github.com/foundryvtt/dnd5e/blob/4.3.x/module/applications/combat/combat-tracker.mjs -*/ - -export class RipCryptCombat extends Combat { - - get customGroups() { - let groups = new Map(); - - for (const combatant of this.combatants) { - const groupKey = combatant.groupKey; - if (!groupKey) { continue }; - - if (groups.has(groupKey)) { - groups.get(groupKey).push(combatant); - } - else { - groups.set(groupKey, [combatant]); - }; - }; - - return groups; - }; - - /** - * @override - * Sorts combatants for the combat tracker in the following way: - * - Distance from the current fate ordinal. (0 -> 3) - * - Coin Flip result (if disposition matches flip result, then 0, otherwise, 0.5) - */ - _sortCombatants(a, b) { - const ia = Number.isNumeric(a.dynamicInitiative) ? a.dynamicInitiative : -Infinity; - const ib = Number.isNumeric(b.dynamicInitiative) ? b.dynamicInitiative : -Infinity; - - const delta = ia - ib; - if (Math.sign(delta) !== 0) { - return delta; - }; - - // fallback to alphabetical sort - return a.name < b.name ? -1 : 1; - }; - - async nextTurn() { - if (this.round === 0) {return this.nextRound()} - - const turn = this.turn ?? -1; - - const groupKey = this.turns[turn]?.groupKey; - - // Determine the next turn number - let nextTurn = null; - for (let i = turn + 1; i < this.turns.length; i++) { - const combatant = this.turns[i]; - if (combatant.groupKey !== groupKey) { - nextTurn = i; - break; - }; - }; - - // Maybe advance to the next round - if ((nextTurn === null) || (nextTurn >= this.turns.length)) {return this.nextRound()} - - const advanceTime = this.getTimeDelta(this.round, this.turn, this.round, nextTurn); - - // Update the document, passing data through a hook first - const updateData = {round: this.round, turn: nextTurn}; - const updateOptions = {direction: 1, worldTime: {delta: advanceTime}}; - Hooks.callAll(`combatTurn`, this, updateData, updateOptions); - await this.update(updateData, updateOptions); - return this; - }; - - async previousTurn() { - if (this.round === 0) { return this } - if ((this.turn === 0) || (this.turns.length === 0)) {return this.previousRound()} - - const currentTurn = (this.turn ?? this.turns.length) - 1; - let previousTurn = null; - const groupKey = this.combatant.groupKey; - for (let i = currentTurn; i >= 0; i--) { - const combatant = this.turns[i]; - if (combatant.groupKey !== groupKey) { - previousTurn = i; - break; - } - } - - if (previousTurn < 0) { - if (this.round === 1) { - this.round = 0; - return this; - }; - return this.previousRound(); - } - - const advanceTime = this.getTimeDelta(this.round, this.turn, this.round, previousTurn); - - // Update the document, passing data through a hook first - const updateData = {round: this.round, turn: previousTurn}; - const updateOptions = {direction: -1, worldTime: {delta: advanceTime}}; - Hooks.callAll(`combatTurn`, this, updateData, updateOptions); - await this.update(updateData, updateOptions); - return this; - }; - - /** - * Overridden to make it so that there can be multiple tokens with turn markers - * visible at the same time. - * - * @protected - * @internal - * @override - */ - _updateTurnMarkers() { - if (!canvas.ready) { return }; - - const tokenGroup = this.combatant?.groupKey; - for (const token of canvas.tokens.turnMarkers) { - const actor = token.actor ?? token.baseActor; - if (actor?.groupKey !== tokenGroup) { - token.renderFlags.set({refreshTurnMarker: true}); - } - } - - if (!this.active) { return }; - const currentToken = this.combatant?.token?._object; - if (!tokenGroup && currentToken) { - currentToken.renderFlags.set({refreshTurnMarker: true}); - } - 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 deleted file mode 100644 index 128f042..0000000 --- a/module/documents/combatant.mjs +++ /dev/null @@ -1,71 +0,0 @@ -import { distanceBetweenFates } from "../utils/fates.mjs"; - -export class RipCryptCombatant extends Combatant { - - get disposition() { - switch (this.token?.disposition) { - case CONST.TOKEN_DISPOSITIONS.HOSTILE: - return `hostile`; - case CONST.TOKEN_DISPOSITIONS.FRIENDLY: - return `friendly`; - }; - return `unknown`; - }; - - /** - * Used by the Combat tracker to order combatants according to their - * fate path and the coin flip. - */ - get dynamicInitiative() { - let total = 0; - - const start = game.settings.get(`ripcrypt`, `currentFate`); - const end = this.actor?.system?.fate || this.baseActor?.system?.fate; - total += distanceBetweenFates(start, end); - - const whoFirst = game.settings.get(`ripcrypt`, `whoFirst`); - if (whoFirst) { - const disposition = this.disposition; - if (disposition === `unknown`) { - total += 0.25; - } - else if (whoFirst !== disposition) { - total += 0.5; - }; - }; - - return total; - }; - - get groupKey() { - const path = this.token?.actor?.system?.fate; - - // Disallow grouping things that don't have a fate path - if (!path) { return null }; - - // Token Disposition (group into: friendlies, unknown, hostiles) - let disposition = this.disposition; - - return `${path}:${disposition}`; - }; - - /** - * Used to create the turn marker when the combatant is added if they're in - * the group whose turn it is. - * - * @override - */ - _onCreate() { - this.token?._object?._refreshTurnMarker(); - }; - - /** - * Used to remove the turn marker when the combatant is removed from combat - * if they had it visible so that it doesn't stick around infinitely. - * - * @override - */ - _onDelete() { - this.token?._object?._refreshTurnMarker(); - }; -}; diff --git a/module/documents/item.mjs b/module/documents/item.mjs deleted file mode 100644 index ac1d188..0000000 --- a/module/documents/item.mjs +++ /dev/null @@ -1,8 +0,0 @@ -export class RipCryptItem extends Item { - get quantifiedName() { - if (this.system.quantity != null && this.system.quantity !== 1) { - return `${this.name} (${this.system.quantity})`; - }; - return this.name; - }; -}; diff --git a/module/documents/token.mjs b/module/documents/token.mjs deleted file mode 100644 index 9492339..0000000 --- a/module/documents/token.mjs +++ /dev/null @@ -1,36 +0,0 @@ -const { Token } = foundry.canvas.placeables; -const { TokenTurnMarker } = foundry.canvas.placeables.tokens; - -export class RipCryptToken extends Token { - /** - * Overridden using a slightly modified implementation in order to make it so - * that the turn marker shows up on tokens if they're in the same group as the - * currently active combatant - * - * @override - */ - _refreshTurnMarker() { - // Should a Turn Marker be active? - const {turnMarker} = this.document; - const markersEnabled = CONFIG.Combat.settings.turnMarker.enabled - && (turnMarker.mode !== CONST.TOKEN_TURN_MARKER_MODES.DISABLED); - const combatant = game.combat?.active ? game.combat.combatant : null; - const isTurn = combatant && (combatant.groupKey === this.combatant?.groupKey); - const isDefeated = combatant && combatant.isDefeated; - const markerActive = markersEnabled && isTurn && !isDefeated; - - // Activate a Turn Marker - if (markerActive) { - if (!this.turnMarker) { - this.turnMarker = this.addChildAt(new TokenTurnMarker(this), 0); - }; - canvas.tokens.turnMarkers.add(this); - this.turnMarker.draw(); - } - else if (this.turnMarker) { - canvas.tokens.turnMarkers.delete(this); - this.turnMarker.destroy(); - this.turnMarker = null; - } - } -}; diff --git a/module/flags/item.mjs b/module/flags/item.mjs deleted file mode 100644 index de53d3b..0000000 --- a/module/flags/item.mjs +++ /dev/null @@ -1,4 +0,0 @@ -export const ItemFlags = Object.freeze({ - /** The boolean value to indicate if an item is considered favourited/starred or not */ - FAVOURITE: `favourited`, -}); diff --git a/module/gameTerms.mjs b/module/gameTerms.mjs index 86507ad..b1a1130 100644 --- a/module/gameTerms.mjs +++ b/module/gameTerms.mjs @@ -1,51 +1,20 @@ export const gameTerms = Object.preventExtensions({ - Abilities: Object.freeze({ - GRIT: `grit`, - GRIP: `grip`, - GAIT: `gait`, - GLIM: `glim`, - THINGLIM: `thin-glim`, - }), - Aspects: Object.freeze({ - FOCUS: `focus`, - FLECT: `flect`, - FRACT: `fract`, - }), - FatePath: Object.freeze({ - NORTH: `North`, - EAST: `East`, - SOUTH: `South`, - WEST: `West`, - }), + FatePath: [ + `North`, + `East`, + `South`, + `West`, + ], Access: [ `Common`, `Uncommon`, `Rare`, `Scarce`, ], - Rank: Object.freeze({ - NOVICE: `novice`, - ADEPT: `adept`, - EXPERT: `expert`, - MASTER: `master`, - }), - Anatomy: Object.freeze({ - HEAD: `head`, - BODY: `body`, - ARMS: `arms`, - LEGS: `legs`, - }), - /** The types of items that contribute to the gear limit */ - gearItemTypes: new Set([ - `ammo`, - `armour`, - `weapon`, - `shield`, - `good`, - ]), - WeightRatings: Object.freeze({ - LIGHT: `light`, - MODEST: `modest`, - HEAVY: `heavy`, - }), + Rank: { + NOVICE: `Novice`, + ADEPT: `Adept`, + EXPERT: `Expert`, + Master: `Master`, + }, }); diff --git a/module/handlebarHelpers/_index.mjs b/module/handlebarHelpers/_index.mjs index 9c8587d..1603faf 100644 --- a/module/handlebarHelpers/_index.mjs +++ b/module/handlebarHelpers/_index.mjs @@ -1,10 +1,8 @@ import { handlebarsLocalizer, localizer } from "../utils/Localizer.mjs"; -import { formFields } from "./inputs/formFields.mjs"; import { options } from "./options.mjs"; export default { // #region Complex - "rc-formFields": formFields, "rc-i18n": handlebarsLocalizer, "rc-options": options, diff --git a/module/handlebarHelpers/inputs/barInput.mjs b/module/handlebarHelpers/inputs/barInput.mjs deleted file mode 100644 index f72983e..0000000 --- a/module/handlebarHelpers/inputs/barInput.mjs +++ /dev/null @@ -1,36 +0,0 @@ -import { localizer } from "../../utils/Localizer.mjs"; - -export function barInput(input, data) { - const label = localizer(input.label); - - // Trying to do limited bar info is... annoying to do. - if (data.meta.limited && input.limited) { - return ``; - }; - - return `
- -
- - -
-
`; -}; diff --git a/module/handlebarHelpers/inputs/booleanInput.mjs b/module/handlebarHelpers/inputs/booleanInput.mjs deleted file mode 100644 index c3db3c3..0000000 --- a/module/handlebarHelpers/inputs/booleanInput.mjs +++ /dev/null @@ -1,30 +0,0 @@ -import { localizer } from "../../utils/Localizer.mjs"; - -export function booleanInput(input, data) { - const label = localizer(input.label); - const id = `${data.meta.idp}-${input.id}`; - - if (data.meta.limited) { - return `
- ${label} -
- ??? -
-
`; - }; - - return `
- -
- -
-
`; -}; diff --git a/module/handlebarHelpers/inputs/currency.mjs b/module/handlebarHelpers/inputs/currency.mjs deleted file mode 100644 index 12b6ca8..0000000 --- a/module/handlebarHelpers/inputs/currency.mjs +++ /dev/null @@ -1,33 +0,0 @@ -import { groupInput } from "./groupInput.mjs"; - -export function costInput(input, data) { - return groupInput({ - title: input.label, - fields: [ - { - id: input.id + `-gold`, - type: `integer`, - label: `RipCrypt.common.currency.gold`, - value: input.gold, - path: `system.cost.gold`, - limited: input.limited, - }, - { - id: input.id + `-silver`, - type: `integer`, - label: `RipCrypt.common.currency.silver`, - value: input.silver, - path: `system.cost.silver`, - limited: input.limited, - }, - { - id: input.id + `-copper`, - type: `integer`, - label: `RipCrypt.common.currency.copper`, - value: input.copper, - path: `system.cost.copper`, - limited: input.limited, - }, - ], - }, data); -}; diff --git a/module/handlebarHelpers/inputs/dropdownInput.mjs b/module/handlebarHelpers/inputs/dropdownInput.mjs deleted file mode 100644 index 9b19a6e..0000000 --- a/module/handlebarHelpers/inputs/dropdownInput.mjs +++ /dev/null @@ -1,36 +0,0 @@ -import { localizer } from "../../utils/Localizer.mjs"; -import { options } from "../options.mjs"; - -export function dropdownInput(input, data) { - const label = localizer(input.label); - const id = `${data.meta.idp}-${input.id}`; - - if (!data.meta.editable) { - return `
- ${label} - ${data.meta.limited && input.limited ? `???` : input.value} -
`; - }; - - if (!input.options.length) { - throw new Error(`dropdown type inputs must have some options`); - }; - - return `
- - -
`; -}; diff --git a/module/handlebarHelpers/inputs/formFields.mjs b/module/handlebarHelpers/inputs/formFields.mjs deleted file mode 100644 index d8cd18e..0000000 --- a/module/handlebarHelpers/inputs/formFields.mjs +++ /dev/null @@ -1,47 +0,0 @@ -import { barInput } from "./barInput.mjs"; -import { booleanInput } from "./booleanInput.mjs"; -import { costInput } from "./currency.mjs"; -import { dropdownInput } from "./dropdownInput.mjs"; -import { groupInput } from "./groupInput.mjs"; -import { numberInput } from "./numberInput.mjs"; -import { prosemirrorInput } from "./prosemirrorInput.mjs"; -import { stringSet } from "./stringSet.mjs"; -import { textInput } from "./textInput.mjs"; - -const { getType } = foundry.utils; - -const inputTypes = { - "string-set": stringSet, - prosemirror: prosemirrorInput, - integer: numberInput, - bar: barInput, - dropdown: dropdownInput, - boolean: booleanInput, - group: groupInput, - text: textInput, - cost: costInput, -}; - -const typesToSanitize = new Set([ `string`, `number` ]); - -export function formFields(inputs, opts) { - const fields = []; - for (const input of inputs) { - if (inputTypes[input.type] == null) { continue }; - - if (input.type !== `group`) { - input.limited ??= true; - }; - - if ( - input.type !== `prosemirror` - && typesToSanitize.has(getType(input.value)) - ) { - input.value = Handlebars.escapeExpression(input.value); - }; - fields.push(inputTypes[input.type](input, opts.data.root)); - }; - return fields - .filter(i => i.length > 0) - .join(opts.hash?.joiner ?? `
`); -}; diff --git a/module/handlebarHelpers/inputs/groupInput.mjs b/module/handlebarHelpers/inputs/groupInput.mjs deleted file mode 100644 index 59f26e8..0000000 --- a/module/handlebarHelpers/inputs/groupInput.mjs +++ /dev/null @@ -1,26 +0,0 @@ -import { formFields } from "./formFields.mjs"; -import { localizer } from "../../utils/Localizer.mjs"; - -export function groupInput(input, data) { - const title = localizer(input.title); - - const content = formFields( - input.fields, - { - data: { root: data }, - hash: { joiner: input.joiner ?? `` }, - }, - ); - - return ` -
${title}
-
- ${content} -
-
`; -}; diff --git a/module/handlebarHelpers/inputs/numberInput.mjs b/module/handlebarHelpers/inputs/numberInput.mjs deleted file mode 100644 index 8407912..0000000 --- a/module/handlebarHelpers/inputs/numberInput.mjs +++ /dev/null @@ -1,33 +0,0 @@ -import { localizer } from "../../utils/Localizer.mjs"; - -export function numberInput(input, data) { - const label = localizer(input.label); - const id = `${data.meta.idp}-${input.id}`; - - if (!data.meta.editable) { - return `
- ${label} - ${data.meta.limited && input.limited ? `???` : input.value} -
`; - }; - - let attrs = ``; - if (input.min != undefined) { attrs += ` min="${input.min}"` }; - if (input.max != undefined) { attrs += ` max="${input.max}"` }; - if (input.step != undefined) { attrs += `step="${input.step}"` }; - - return `
- - -
`; -}; diff --git a/module/handlebarHelpers/inputs/prosemirrorInput.mjs b/module/handlebarHelpers/inputs/prosemirrorInput.mjs deleted file mode 100644 index df84e6c..0000000 --- a/module/handlebarHelpers/inputs/prosemirrorInput.mjs +++ /dev/null @@ -1,43 +0,0 @@ -import { localizer } from "../../utils/Localizer.mjs"; - -export function prosemirrorInput(input, data) { - const label = localizer(input.label); - - if (!data.meta.editable) { - return `
-
-
- ${label} -
-
-
- ${input.value} -
-
`; - }; - - return `
-
-
- ${label} -
- -
- - -
${input.value}
-
`; -}; diff --git a/module/handlebarHelpers/inputs/stringSet.mjs b/module/handlebarHelpers/inputs/stringSet.mjs deleted file mode 100644 index 1f059ac..0000000 --- a/module/handlebarHelpers/inputs/stringSet.mjs +++ /dev/null @@ -1,51 +0,0 @@ -import { localizer } from "../../utils/Localizer.mjs"; - -export function stringSet(input, data) { - const label = localizer(input.label); - const placeholder = localizer(input.placeholder ?? ``); - const id = `${data.meta.idp}-${input.id}`; - - if (!data.meta.editable) { - const tagList = input.value - .split(/,\s*/) - .filter(t => t.length > 0) - .map(t => { - return `
${t.trim()}
`; - }); - let count = tagList.length; - let tags = tagList.join(``); - - if (tagList.length === 0) { - tags = `---`; - }; - - if (data.meta.limited && input.limited) { - count = 0; - tags = `???`; - }; - - return `
- ${label} -
- ${tags} -
-
`; - }; - - return `
- - -
`; -}; diff --git a/module/handlebarHelpers/inputs/textInput.mjs b/module/handlebarHelpers/inputs/textInput.mjs deleted file mode 100644 index fbb3fc4..0000000 --- a/module/handlebarHelpers/inputs/textInput.mjs +++ /dev/null @@ -1,27 +0,0 @@ -import { localizer } from "../../utils/Localizer.mjs"; - -export function textInput(input, data) { - const label = localizer(input.label); - const id = `${data.meta.idp}-${input.id}`; - - if (!data.meta.editable) { - return `
- ${label} - ${data.meta.limited && input.limited ? `???` : input.value} -
`; - }; - - return `
- - -
`; -}; diff --git a/module/hooks/init.mjs b/module/hooks/init.mjs index 28c4fd9..c5ad784 100644 --- a/module/hooks/init.mjs +++ b/module/hooks/init.mjs @@ -1,134 +1,57 @@ // 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"; -import { RipCryptCombatTracker } from "../Apps/sidebar/CombatTracker.mjs"; -import { SkillsCardV1 } from "../Apps/ActorSheets/SkillsCardV1.mjs"; -import { StatsCardV1 } from "../Apps/ActorSheets/StatsCardV1.mjs"; +import { HeroSkillsCardV1 } from "../Apps/ActorSheets/HeroSkillsCardV1.mjs"; +import { HeroSummaryCardV1 } from "../Apps/ActorSheets/HeroSummaryCardV1.mjs"; // Data Models -import { AmmoData } from "../data/Item/Ammo.mjs"; -import { ArmourData } from "../data/Item/Armour.mjs"; -import { CraftData } from "../data/Item/Craft.mjs"; -import { GeistData } from "../data/Actor/Geist.mjs"; -import { GoodData } from "../data/Item/Good.mjs"; import { HeroData } from "../data/Actor/Hero.mjs"; -import { ShieldData } from "../data/Item/Shield.mjs"; -import { SkillData } from "../data/Item/Skill.mjs"; import { WeaponData } from "../data/Item/Weapon.mjs"; // Class Overrides import { CryptDie } from "../dice/CryptDie.mjs"; -// Documents -import { RipCryptCombat } from "../documents/combat.mjs"; -import { RipCryptCombatant } from "../documents/combatant.mjs"; -import { RipCryptItem } from "../documents/item.mjs"; -import { RipCryptToken } from "../documents/token.mjs"; - // Misc import helpers from "../handlebarHelpers/_index.mjs"; import { Logger } from "../utils/Logger.mjs"; -import { registerCustomComponents } from "../Apps/components/_index.mjs"; +import { registerCustomComponents } from "../Apps/elements/_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; Hooks.once(`init`, () => { Logger.log(`Initializing`); - CONFIG.Combat.initiative.decimals = 2; - CONFIG.ui.delveDice = DelveDiceHUD; - // #region Settings - registerMetaSettings(); registerDevSettings(); registerUserSettings(); - registerWorldSettings(); // #endregion // #region Datamodels CONFIG.Actor.dataModels.hero = HeroData; - CONFIG.Actor.dataModels.geist = GeistData; - CONFIG.Item.dataModels.ammo = AmmoData; - CONFIG.Item.dataModels.armour = ArmourData; - CONFIG.Item.dataModels.craft = CraftData; - CONFIG.Item.dataModels.good = GoodData; - CONFIG.Item.dataModels.shield = ShieldData; - CONFIG.Item.dataModels.skill = SkillData; CONFIG.Item.dataModels.weapon = WeaponData; // #endregion // #region Class Changes - CONFIG.ui.combat = RipCryptCombatTracker; - CONFIG.Combat.documentClass = RipCryptCombat; - CONFIG.Combatant.documentClass = RipCryptCombatant; - CONFIG.Token.objectClass = RipCryptToken; - CONFIG.Item.documentClass = RipCryptItem; CONFIG.Dice.terms.d = CryptDie; // #endregion // #region Sheets // #region Actors - Actors.registerSheet(game.system.id, CombinedHeroSheet, { + Actors.registerSheet(game.system.id, HeroSummaryCardV1, { makeDefault: true, types: [`hero`], - label: `RipCrypt.sheet-names.CombinedHeroSheet`, - themes: CombinedHeroSheet.themes, + label: `RipCrypt.sheet-names.HeroSummaryCardV1`, + themes: HeroSummaryCardV1.themes, }); - Actors.registerSheet(game.system.id, StatsCardV1, { + Actors.registerSheet(game.system.id, HeroSkillsCardV1, { types: [`hero`], - label: `RipCrypt.sheet-names.StatsCardV1`, - themes: StatsCardV1.themes, - }); - Actors.registerSheet(game.system.id, StatsCardV1, { - makeDefault: true, - types: [`geist`], - label: `RipCrypt.sheet-names.StatsCardV1`, - themes: StatsCardV1.themes, - }); - Actors.registerSheet(game.system.id, SkillsCardV1, { - types: [`hero`, `geist`], - label: `RipCrypt.sheet-names.SkillsCardV1`, - themes: SkillsCardV1.themes, - }); - Actors.registerSheet(game.system.id, CraftCardV1, { - types: [`hero`, `geist`], - label: `RipCrypt.sheet-names.CraftCardV1`, - themes: CraftCardV1.themes, - }); - // #endregion - - // #region Items - Items.registerSheet(game.system.id, AllItemSheetV1, { - makeDefault: true, - 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`], + label: `RipCrypt.sheet-names.HeroSkillsCardV1`, + themes: HeroSkillsCardV1.themes, }); // #endregion // #endregion // #region Token Attrs 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 e77e0e7..6536a48 100644 --- a/module/hooks/ready.mjs +++ b/module/hooks/ready.mjs @@ -1,4 +1,4 @@ -import { filePath } from "../consts.mjs"; +import { CryptApp } from "../Apps/CryptApp.mjs"; import { Logger } from "../utils/Logger.mjs"; Hooks.once(`ready`, () => { @@ -6,30 +6,19 @@ Hooks.once(`ready`, () => { let defaultTab = game.settings.get(`ripcrypt`, `defaultTab`); if (defaultTab) { - try { + if (!ui.sidebar?.TABS?.[defaultTab]) { + Logger.error(`Couldn't find a sidebar tab with ID:`, defaultTab); + } else { Logger.debug(`Switching sidebar tab to:`, defaultTab); - ui.sidebar.changeTab(defaultTab, `primary`); - } - catch { - Logger.error(`Failed to change to sidebar tab:`, defaultTab); + ui.sidebar.activateTab(defaultTab); }; }; if (game.settings.get(`ripcrypt`, `devMode`)) { ui.sidebar.expand(); - if (game.paused) { game.togglePause(false, { broadcast: true }) }; + if (game.paused) { game.togglePause() }; }; - ui.delveDice.render({ force: true }); - - // MARK: 1-time updates - if (!game.settings.get(`ripcrypt`, `firstLoadFinished`)) { - // Update the turnMarker to be the RipCrypt defaults - const combatConfig = game.settings.get(`core`, `combatTrackerConfig`); - combatConfig.turnMarker.src = filePath(`assets/turn-marker.png`); - combatConfig.turnMarker.animation = `spinPulse`; - game.settings.set(`core`, `combatTrackerConfig`, combatConfig); - }; - - game.settings.set(`ripcrypt`, `firstLoadFinished`, true); + CONFIG.ui.crypt = new CryptApp(); + CONFIG.ui.crypt.render({ force: true }); }); diff --git a/module/main.mjs b/module/main.mjs index 064d9f8..58ec33d 100644 --- a/module/main.mjs +++ b/module/main.mjs @@ -2,6 +2,3 @@ import "./hooks/init.mjs"; import "./hooks/ready.mjs"; import "./hooks/hotReload.mjs"; - -// Global API -import "./api.mjs"; diff --git a/module/settings/metaSettings.mjs b/module/settings/metaSettings.mjs deleted file mode 100644 index 5acdbe9..0000000 --- a/module/settings/metaSettings.mjs +++ /dev/null @@ -1,61 +0,0 @@ -import { gameTerms } from "../gameTerms.mjs"; - -const { StringField } = foundry.data.fields; -const { FatePath } = gameTerms; - -export function registerMetaSettings() { - game.settings.register(`ripcrypt`, `dc`, { - scope: `world`, - type: Number, - default: 5, - config: false, - requiresReload: false, - onChange: () => { - ui.delveDice.render({ parts: [`difficulty`] }); - }, - }); - - game.settings.register(`ripcrypt`, `sandsOfFate`, { - scope: `world`, - type: Number, - default: 8, - config: false, - requiresReload: false, - onChange: async () => { - ui.delveDice.animate({ parts: [`sandsOfFate`] }); - }, - }); - - game.settings.register(`ripcrypt`, `currentFate`, { - scope: `world`, - type: new StringField({ - blank: false, - nullable: false, - initial: FatePath.NORTH, - }), - config: false, - requiresReload: false, - onChange: async () => { - ui.delveDice.animate({ parts: [`fateCompass`] }); - }, - }); - - game.settings.register(`ripcrypt`, `whoFirst`, { - scope: `world`, - type: String, - config: false, - requiresReload: false, - default: `friendly`, - onChange: async () => { - await game.combat?.setupTurns(); - await ui.combat.render({ parts: [ `tracker` ] }); - }, - }); - - game.settings.register(`ripcrypt`, `firstLoadFinished`, { - scope: `world`, - type: Boolean, - default: false, - requiresReload: false, - }); -}; diff --git a/module/settings/userSettings.mjs b/module/settings/userSettings.mjs index 400ec7c..18757f4 100644 --- a/module/settings/userSettings.mjs +++ b/module/settings/userSettings.mjs @@ -1,23 +1,13 @@ export function registerUserSettings() { - /* ! Non-Functional + const userScope = game.release.generation >= 13 ? `user` : `client`; + game.settings.register(`ripcrypt`, `abbrAccess`, { name: `RipCrypt.setting.abbrAccess.name`, hint: `RipCrypt.setting.abbrAccess.hint`, - scope: `user`, + scope: userScope, type: Boolean, config: true, default: false, requiresReload: false, }); - */ - - game.settings.register(`ripcrypt`, `condensedRange`, { - name: `RipCrypt.setting.condensedRange.name`, - hint: `RipCrypt.setting.condensedRange.hint`, - scope: `user`, - type: Boolean, - config: true, - default: true, - requiresReload: false, - }); }; diff --git a/module/settings/worldSettings.mjs b/module/settings/worldSettings.mjs deleted file mode 100644 index ac1643c..0000000 --- a/module/settings/worldSettings.mjs +++ /dev/null @@ -1,52 +0,0 @@ -const { NumberField, StringField } = foundry.data.fields; - -export function registerWorldSettings() { - game.settings.register(`ripcrypt`, `sandsOfFateInitial`, { - name: `RipCrypt.setting.sandsOfFateInitial.name`, - hint: `RipCrypt.setting.sandsOfFateInitial.hint`, - scope: `world`, - config: true, - requiresReload: false, - type: new NumberField({ - required: true, - min: 1, - step: 1, - max: 10, - initial: 8, - }), - onChange: async (newInitialSands) => { - const currentSands = game.settings.get(`ripcrypt`, `sandsOfFate`); - if (newInitialSands <= currentSands) { - game.settings.set(`ripcrypt`, `sandsOfFate`, newInitialSands); - }; - }, - }); - - game.settings.register(`ripcrypt`, `onCrypticEvent`, { - name: `RipCrypt.setting.onCrypticEvent.name`, - hint: `RipCrypt.setting.onCrypticEvent.hint`, - scope: `world`, - config: true, - requiresReload: false, - type: new StringField({ - required: true, - initial: `notif`, - choices: { - "notif": `RipCrypt.setting.onCrypticEvent.options.notif`, - "pause": `RipCrypt.setting.onCrypticEvent.options.pause`, - "both": `RipCrypt.setting.onCrypticEvent.options.both`, - "nothing": `RipCrypt.setting.onCrypticEvent.options.nothing`, - }, - }), - }); - - 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 deleted file mode 100644 index bcb2b5e..0000000 --- a/module/sockets/_index.mjs +++ /dev/null @@ -1,29 +0,0 @@ -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 deleted file mode 100644 index 072e5af..0000000 --- a/module/sockets/notify.mjs +++ /dev/null @@ -1,56 +0,0 @@ -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 deleted file mode 100644 index 8560b6d..0000000 --- a/module/sockets/updateSands.mjs +++ /dev/null @@ -1,38 +0,0 @@ -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/Logger.mjs b/module/utils/Logger.mjs index 70c6481..fc1b51c 100644 --- a/module/utils/Logger.mjs +++ b/module/utils/Logger.mjs @@ -15,7 +15,7 @@ const augmentedProps = new Set([ export const Logger = new Proxy(console, { get(target, prop, _receiver) { if (augmentedProps.has(prop)) { - return target[prop].bind(target, game.system.id, `|`); + return (...args) => target[prop](game.system.id, `|`, ...args); }; return target[prop]; }, diff --git a/module/utils/PopoverEventManager.mjs b/module/utils/PopoverEventManager.mjs deleted file mode 100644 index 07e4793..0000000 --- a/module/utils/PopoverEventManager.mjs +++ /dev/null @@ -1,184 +0,0 @@ -import { getTooltipDelay } from "../consts.mjs"; -import { Logger } from "./Logger.mjs"; - -export class PopoverEventManager { - #options; - #id; - - get id() { - return this.#id; - }; - - /** @type {Map} */ - static #existing = new Map(); - - /** - * @param {HTMLElement} element The element to attach the listeners to. - * @param {GenericPopoverMixin} popoverClass The class reference that represents the popover app - */ - constructor(id, element, popoverClass, options = {}) { - id = `${id}-${popoverClass.name}`; - this.#id = id; - - if (PopoverEventManager.#existing.has(id)) { - const manager = PopoverEventManager.#existing.get(id); - manager.#addListeners(element); - return manager; - }; - - options.managerId = id; - options.locked ??= false; - options.lockable ??= true; - - this.#options = options; - this.#element = element; - this.#class = popoverClass; - - this.#addListeners(element); - PopoverEventManager.#existing.set(id, this); - }; - - /** - * @param {HTMLElement} element - */ - #addListeners(element) { - element.addEventListener(`pointerenter`, this.#pointerEnterHandler.bind(this)); - element.addEventListener(`pointerout`, this.#pointerOutHandler.bind(this)); - element.addEventListener(`click`, this.#clickHandler.bind(this)); - - if (this.#options.lockable) { - element.addEventListener(`pointerup`, this.#pointerUpHandler.bind(this)); - }; - }; - - destroy() { - this.close(); - this.#element.removeEventListener(`pointerenter`, this.#pointerEnterHandler); - this.#element.removeEventListener(`pointerout`, this.#pointerOutHandler); - this.#element.removeEventListener(`click`, this.#clickHandler); - if (this.#options.lockable) { - this.#element.removeEventListener(`pointerup`, this.#pointerUpHandler); - }; - this.#stopOpen(); - this.#stopClose(); - }; - - close() { - this.#frameless?.close({ force: true }); - this.#framed?.close({ force: true }); - }; - - #stopOpen() { - if (this.#openTimeout != null) { - clearTimeout(this.#openTimeout); - this.#openTimeout = null; - }; - }; - - #stopClose() { - if (this.#closeTimeout != null) { - clearTimeout(this.#closeTimeout); - this.#closeTimeout = null; - } - }; - - get rendered() { - return Boolean(this.#frameless?.rendered || this.#framed?.rendered); - }; - - render(options) { - if (this.#framed?.rendered) { - this.#framed.render(options); - }; - if (this.#frameless?.rendered) { - this.#frameless.render(options); - }; - }; - - #element; - #class; - #openTimeout = null; - #closeTimeout = null; - - #frameless; - #framed; - - #construct(options) { - options.popover ??= {}; - options.popover.managerId = this.#id; - - return new this.#class(options); - }; - - #clickHandler() { - Logger.debug(`click event handler`); - // Cleanup for the frameless lifecycle - this.#stopOpen(); - this.#stopClose(); - this.#frameless?.close({ force: true }); - - if (!this.#framed) { - this.#framed = this.#construct({ popover: { ...this.#options, framed: true } }); - } - this.#framed?.render({ force: true }); - }; - - #pointerEnterHandler(event) { - this.#stopClose(); - - const pos = event.target.getBoundingClientRect(); - const x = pos.x + Math.floor(pos.width / 2); - const y = pos.y; - - this.#openTimeout = setTimeout( - () => { - this.#openTimeout = null; - - // When we have the framed version rendered, we might as well just focus - // it instead of rendering a new application - if (this.#framed?.rendered) { - this.#framed.bringToFront(); - return; - }; - - // When the frameless is already rendered, we should just move it to the - // new location instead of spawning a new one - if (this.#frameless?.rendered) { - const { width, height } = this.#frameless.element.getBoundingClientRect(); - const top = y - height; - const left = x - Math.floor(width / 2); - this.#frameless.setPosition({ left, top }); - return; - } - - this.#frameless = this.#construct({ - popover: { - ...this.#options, - framed: false, - x, y, - }, - }); - this.#frameless?.render({ force: true }); - }, - getTooltipDelay(), - ); - }; - - #pointerOutHandler() { - this.#stopOpen(); - - this.#closeTimeout = setTimeout( - () => { - this.#closeTimeout = null; - this.#frameless?.close(); - }, - getTooltipDelay(), - ); - }; - - #pointerUpHandler(event) { - if (event.button !== 1 || !this.#frameless?.rendered || Tour.tourInProgress) { return }; - event.preventDefault(); - this.#frameless.toggleLock(); - }; -}; diff --git a/module/utils/clamp.mjs b/module/utils/clamp.mjs deleted file mode 100644 index 94cac4e..0000000 --- a/module/utils/clamp.mjs +++ /dev/null @@ -1,3 +0,0 @@ -export function clamp(min, ideal, max) { - return Math.max(min, Math.min(ideal, max)); -}; diff --git a/module/utils/fates.mjs b/module/utils/fates.mjs deleted file mode 100644 index d1fb6dd..0000000 --- a/module/utils/fates.mjs +++ /dev/null @@ -1,51 +0,0 @@ -import { gameTerms } from "../gameTerms.mjs"; -import { Logger } from "./Logger.mjs"; - -const { FatePath } = gameTerms; - -export function isOppositeFates(a, b) { - return (a === FatePath.NORTH && b === FatePath.SOUTH) - || (a === FatePath.EAST && b === FatePath.WEST); -}; - -export function distanceBetweenFates(start, end) { - if (!start || !end) { - Logger.error(`Start and End must both have a defined value, given`, {start, end}); - return undefined; - }; - - if (start === end) { - return 0; - }; - - if (isOppositeFates(start, end) || isOppositeFates(end, start)) { - return 2; - }; - - let isForward = start === FatePath.SOUTH && end === FatePath.WEST; - isForward ||= start === FatePath.NORTH && end === FatePath.EAST; - isForward ||= start === FatePath.WEST && end === FatePath.NORTH; - isForward ||= start === FatePath.EAST && end === FatePath.SOUTH; - if (isForward) { - return 1; - }; - return 3; -}; - -const fateOrder = [ - FatePath.WEST, // to make the .find not integer overflow - FatePath.NORTH, - FatePath.EAST, - FatePath.SOUTH, - FatePath.WEST, -]; - -export function nextFate(fate) { - const fateIndex = fateOrder.findIndex(f => f === fate); - return fateOrder[fateIndex + 1]; -}; - -export function previousFate(fate) { - const fateIndex = fateOrder.lastIndexOf(fate); - return fateOrder[fateIndex - 1]; -}; diff --git a/module/utils/rank.mjs b/module/utils/rank.mjs deleted file mode 100644 index 81f6b59..0000000 --- a/module/utils/rank.mjs +++ /dev/null @@ -1,13 +0,0 @@ -import { gameTerms } from "../gameTerms.mjs"; - -/** - * Converts a rank's name into an integer form for use in mathematical calculations - * that rely on rank. - * - * @param {Novice|Adept|Expert|Master} rankName The rank to convert into an integer - * @returns An integer between 1 and 4 - */ -export function rankToInteger(rankName) { - return Object.values(gameTerms.Rank) - .findIndex(r => r === rankName) + 1; -}; diff --git a/package-lock.json b/package-lock.json index af1a200..9384e26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,6 @@ "@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" } }, @@ -776,19 +775,6 @@ "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 5fa77f1..9b335a7 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,9 @@ "@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 deleted file mode 100644 index 6f80750..0000000 --- a/packs/protection/_source/Armour_pZxc6QLgVWfnZlf7.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "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 deleted file mode 100644 index 75dd4a1..0000000 --- a/packs/protection/_source/Breastplate_KQ6uyTPUOHuMTxDF.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "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 deleted file mode 100644 index 225a22c..0000000 --- a/packs/protection/_source/Heavy_BsNUpCnwmlhOWBhZ.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "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 deleted file mode 100644 index 69d4a46..0000000 --- a/packs/protection/_source/Heavy_Shields_uUrCwjxV6Ihisb6V.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "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 deleted file mode 100644 index c7db6f2..0000000 --- a/packs/protection/_source/Leather_Cap_JMkV8kMnCXhW5KDh.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "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 deleted file mode 100644 index 509e0e7..0000000 --- a/packs/protection/_source/Leather__Hide_Bracers_nz4DXXR4iU9CeMRA.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "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 deleted file mode 100644 index f382b54..0000000 --- a/packs/protection/_source/Leather__Hide_Jacket_zMyxSJ6VpaH3ddOO.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "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 deleted file mode 100644 index 8c9a9c3..0000000 --- a/packs/protection/_source/Leather__Hide_Leggings_14Omu9q2sMxW8GWB.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "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 deleted file mode 100644 index bb9b437..0000000 --- a/packs/protection/_source/Light_HRwiz1c1ZcQyPu4z.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "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 deleted file mode 100644 index e04bc0c..0000000 --- a/packs/protection/_source/Light_Shields_a6vPAa25z8L9t79K.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "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 deleted file mode 100644 index 1c008b2..0000000 --- a/packs/protection/_source/Mail__Link__Scale_Coat_Sr40RFsPr2M0bTKK.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "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 deleted file mode 100644 index 708afd3..0000000 --- a/packs/protection/_source/Mail__Link__Scale_Coif_HfG5Doxf7576Jgbt.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "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 deleted file mode 100644 index e1d45ce..0000000 --- a/packs/protection/_source/Mail__Link__Scale_Leggings_YBpElIVQ534pm3Mf.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "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 deleted file mode 100644 index 766f79f..0000000 --- a/packs/protection/_source/Mail__Link__Scale_Shirt_wab6Bo8ngar4mBCN.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "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 deleted file mode 100644 index 5f40713..0000000 --- a/packs/protection/_source/Modest_Shields_fyL8LZ8jpEQbjpM2.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "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 deleted file mode 100644 index 0df0b4f..0000000 --- a/packs/protection/_source/Modest_cKN149ZGLqfyt0oi.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "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 deleted file mode 100644 index b14cd65..0000000 --- a/packs/protection/_source/Plate_Bracers_e8JRJn5Blw3UrvnW.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "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 deleted file mode 100644 index ea89641..0000000 --- a/packs/protection/_source/Plate_Leggings_v1y4RKGad2IXOu5e.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "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 deleted file mode 100644 index 072f340..0000000 --- a/packs/protection/_source/Ring_Coif__Helm_Z4NTsrX63JNjjZ8Z.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "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 deleted file mode 100644 index f561577..0000000 --- a/packs/protection/_source/Shields_RXPJBkzVxFnoT3Tm.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "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 deleted file mode 100644 index f25006d..0000000 --- a/packs/weapons/_source/Ammo_gvNPXXRBx2eGIzcU.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "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 deleted file mode 100644 index 07dc4b5..0000000 --- a/packs/weapons/_source/Arming_Sword_xXUItaoHTQ2QiaX4.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "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 deleted file mode 100644 index 5538980..0000000 --- a/packs/weapons/_source/Arrow_gN9JbmouUI7eOrSj.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "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 deleted file mode 100644 index b36ef0b..0000000 --- a/packs/weapons/_source/Axe__Hammer__Pick_cr35WzuPGDojuOuJ.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index d4249cb..0000000 --- a/packs/weapons/_source/Battleaxe__Warhammer_otIFI9TIDPWnT3cq.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "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 deleted file mode 100644 index ef90dd2..0000000 --- a/packs/weapons/_source/Black_Powder_c86ht86Z9vOEBtNH.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "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 deleted file mode 100644 index 9c307f4..0000000 --- a/packs/weapons/_source/Blowgun_Darts_FvtiEaQhJumPsCwb.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "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 deleted file mode 100644 index 2394a78..0000000 --- a/packs/weapons/_source/Blowgun__Sling_VrG2xer1quhjwUag.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index 7802c4f..0000000 --- a/packs/weapons/_source/Broadsword_I9QaJTU6O2E9WzUS.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "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 deleted file mode 100644 index b174c2b..0000000 --- a/packs/weapons/_source/Club_NlDJVbXeXRfoCZWp.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "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 deleted file mode 100644 index d03ae6d..0000000 --- a/packs/weapons/_source/Crossbow_BNoYUrlpDk6oBeJt.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index 1dea670..0000000 --- a/packs/weapons/_source/Crossbow_Bolts_7cmLLV6o2pPAyyAg.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "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 deleted file mode 100644 index d391acc..0000000 --- a/packs/weapons/_source/Cutlass__Saber__Scimitar_kSWrbdKdYIRxkWka.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index 8ded77a..0000000 --- a/packs/weapons/_source/Dagger_q8z2HptFaPmeHU9n.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "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 deleted file mode 100644 index 6caf1c7..0000000 --- a/packs/weapons/_source/Darts_rDxS6EJzg2zvSpxR.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index 868057d..0000000 --- a/packs/weapons/_source/Flintlock_Pistol_1vxM6KoEPrQ7pjcg.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "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 deleted file mode 100644 index 13105fc..0000000 --- a/packs/weapons/_source/Flintlock_Rifle_xUGUgnjJsKUPgPpX.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "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 deleted file mode 100644 index 6f80b11..0000000 --- a/packs/weapons/_source/Great_Arrows_FQ5VBjR0LdXf8Nh2.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "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 deleted file mode 100644 index ccba1ec..0000000 --- a/packs/weapons/_source/Greataxe__Maul__Sword_Pfm448hGPVSuyyrd.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index a823775..0000000 --- a/packs/weapons/_source/Greatbow_N80F8sq9SaHrXBvS.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index 181532c..0000000 --- a/packs/weapons/_source/Greatclub__Staff_Ct9iNF9KPMGStSQo.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index 0dc3807..0000000 --- a/packs/weapons/_source/Hand_Crossbow_5sUeNom6dn6MaoAE.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index cc22c9f..0000000 --- a/packs/weapons/_source/Hand_Weapons_3mr6aZe43z7YBysA.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "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 deleted file mode 100644 index 729d6f9..0000000 --- a/packs/weapons/_source/Heavy_3tp9cwpArQNOpkAY.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "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 deleted file mode 100644 index bd06196..0000000 --- a/packs/weapons/_source/Heavy_Crossbow_xJzHTrYsJVL2WsSF.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index b7585e5..0000000 --- a/packs/weapons/_source/Heavy_IkSGLBUzPI9Jbcj7.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "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 deleted file mode 100644 index 04d325c..0000000 --- a/packs/weapons/_source/Knife_fv5D0xOJVpOwnyTn.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index f243f42..0000000 --- a/packs/weapons/_source/Light_mmd8siMKSLyOeILo.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "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 deleted file mode 100644 index fb4cbf3..0000000 --- a/packs/weapons/_source/Light_vPyj2cK1j66Zyrul.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "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 deleted file mode 100644 index d20d8c3..0000000 --- a/packs/weapons/_source/Long_Rifle_dn1eja68NNuxB8K1.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "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 deleted file mode 100644 index 57ee032..0000000 --- a/packs/weapons/_source/Longbow_oyVNU8XgMiZI0Uxr.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index 7ca740d..0000000 --- a/packs/weapons/_source/Longsword_7ezV0MrGA0duoGbl.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index ca9314d..0000000 --- a/packs/weapons/_source/Modest_8NNF9jBjpmPpmw1B.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "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 deleted file mode 100644 index 0828e40..0000000 --- a/packs/weapons/_source/Modest_dBAI76CApXH8qqjx.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "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 deleted file mode 100644 index 28cf30c..0000000 --- a/packs/weapons/_source/Poleaxe__Glaive__Halberd_j6C9IyebpKsk7M6R.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index 63aaffe..0000000 --- a/packs/weapons/_source/Quarterstaff_0ebCxTylmQa5UJvF.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index ff8a606..0000000 --- a/packs/weapons/_source/Ranged_Weapons_sjc6X9bKf7BY04Ar.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "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 deleted file mode 100644 index b2a5f0c..0000000 --- a/packs/weapons/_source/Rapier__Foil_cgEQKXKnSShCRQaq.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "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 deleted file mode 100644 index e999370..0000000 --- a/packs/weapons/_source/Scythe_PnBWkLNzmQjXbB94.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index 484b4ab..0000000 --- a/packs/weapons/_source/Shortbow_qmnDO3TrKoeW7DZB.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index 06322d5..0000000 --- a/packs/weapons/_source/Shortsword_UulalWrMRtSX5KxZ.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "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 deleted file mode 100644 index 5338692..0000000 --- a/packs/weapons/_source/Shot_Q5i7hMOPgb9oXmh5.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "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 deleted file mode 100644 index f0c8fe8..0000000 --- a/packs/weapons/_source/Sickle_o9saXoHahbxTxt4h.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "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 deleted file mode 100644 index 477bc8b..0000000 --- a/packs/weapons/_source/Spear__Javelin__Pike_bTOoWxHeLSY9JWNY.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "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 deleted file mode 100644 index b193d2a..0000000 --- a/packs/weapons/_source/Throwing_Axe_n2j1gxnn3WnUPag6.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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 deleted file mode 100644 index 0f102f8..0000000 --- a/packs/weapons/_source/Warclub__Flail__Mace_WMiQdSVgM8z84MEv.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "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 deleted file mode 100644 index 7380fb8..0000000 --- a/packs/weapons/_source/Whip_vVF6LZSFi0pNB95E.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "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 deleted file mode 100644 index 88ab4e4..0000000 --- a/scripts/buildCompendia.mjs +++ /dev/null @@ -1,36 +0,0 @@ -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 deleted file mode 100644 index 0730b38..0000000 --- a/scripts/extractCompendia.mjs +++ /dev/null @@ -1,31 +0,0 @@ -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 deleted file mode 100644 index 3ee94c5..0000000 --- a/scripts/linkFoundry.mjs +++ /dev/null @@ -1,47 +0,0 @@ -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 d4b61ed..c717ddc 100644 --- a/system.json +++ b/system.json @@ -1,24 +1,25 @@ { "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.2.0", + "description": "", + "version": "0.0.1", "compatibility": { - "minimum": 13, - "verified": "13.350", + "minimum": 12, + "verified": 12, "maximum": 13 }, "authors": [ - { "name": "Oliver" } + { + "name": "Oliver Akins", + "url": "https://oliver.akins.me" + } ], "esmodules": [ "module/main.mjs" ], "styles": [ - { - "src": "templates/css/main.css", - "layer": "system" - } + "templates/css/common.css", + "templates/Apps/apps.css" ], "languages": [ { @@ -27,100 +28,23 @@ "path": "langs/en-ca.json" } ], - "url": "https://github.com/Eldritch-Oliver/Foundry-RipCrypt", - "manifest": "https://github.com/Eldritch-Oliver/Foundry-RipCrypt/releases/latest/download/module.json", - "download": "#{DOWNLOAD}#", + "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", "readme": "README.md", "bugs": "", - "socket": true, "flags": { "hotReload": { "extensions": ["css", "hbs", "json", "mjs", "svg"], - "paths": ["assets", "templates", "langs", "module"] + "paths": ["assets", "Apps", "langs", "module"] } }, "documentTypes": { "Actor": { - "hero": {}, - "geist": {} + "hero": {} }, "Item": { - "ammo": {}, - "armour": {}, - "craft": {}, - "good": {}, - "shield": {}, - "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" - ] - } - ] -} + } +} \ No newline at end of file diff --git a/templates/Apps/AllItemSheetV1/content.hbs b/templates/Apps/AllItemSheetV1/content.hbs deleted file mode 100644 index 523c483..0000000 --- a/templates/Apps/AllItemSheetV1/content.hbs +++ /dev/null @@ -1,17 +0,0 @@ -
- {{#if meta.editable}} - - - {{else}} - Name - {{item.name}} - {{/if}} -
- {{{ rc-formFields formFields }}} -
diff --git a/templates/Apps/AllItemSheetV1/style.css b/templates/Apps/AllItemSheetV1/style.css deleted file mode 100644 index 2170d31..0000000 --- a/templates/Apps/AllItemSheetV1/style.css +++ /dev/null @@ -1,119 +0,0 @@ -.ripcrypt .AllItemSheetV1 { - --input-height: 1rem; - --input-underline: none; - --col-gap: 8px; - --row-gap: 8px; - - --string-tags-tag-text: var(--header-text); - --string-tags-tag-background: var(--header-background); - --string-tags-add-text: white; - --string-tags-add-background: var(--accent-1); - --string-tags-input-text: white; - --string-tags-input-background: var(--accent-2); - - --input-text: white; - --input-background: var(--accent-2); - --button-text: white; - --button-background: var(--accent-2); - - --pill-width: 100%; - --pill-border-radius: 4px; - - display: grid; - grid-template-columns: auto 200px; - column-gap: var(--col-gap); - row-gap: var(--row-gap); - max-width: 350px; - - padding: 8px; - background: var(--base-background); - color: var(--base-text); - - [data-input-type] { - display: contents; - } - - > [data-input-type="group"] { - display: unset; - grid-column: 1 / -1; - - > .content { - display: grid; - grid-template-columns: minmax(0, 1fr) minmax(0, 3fr); - column-gap: var(--col-gap); - row-gap: var(--row-gap); - } - } - - > [data-input-type="prose-mirror"] { - grid-column: 1 / -1; - display: flex; - flex-direction: column; - gap: var(--row-gap); - - > .label-row { - display: flex; - flex-direction: row; - width: 100%; - justify-content: space-between; - } - - .value { - background: var(--input-background); - color: var(--input-text); - - > :first-child { - margin-top: 0; - } - > :last-child { - margin-bottom: 0; - } - - &:empty { - display: none; - } - } - } - - hr { - background: var(--accent-1); - grid-column: 1 / -1; - height: 1px; - width: 90%; - margin: 0 auto; - } - - hr:has(+ [data-input-type="group"]), - [data-input-type="group"] + hr { - display: none; - }; - - label, .label { - display: flex; - align-items: center; - box-sizing: border-box; - - padding: 2px 4px; - text-transform: uppercase; - font-size: var(--font-size-14); - overflow: hidden; - text-overflow: ellipsis; - font-weight: bold; - } - - button, input, select, .value, [data-tag-count] { - border-radius: 4px; - padding: 2px 4px; - } - .value, [data-tag-count="0"] { - border: 2px solid var(--accent-2); - } - [data-tag-count="0"] { - justify-content: start; - } - - [data-input-type="boolean"] > .checkbox-container { - display: flex; - justify-content: right; - } -} diff --git a/templates/Apps/ArmourSheet/content.hbs b/templates/Apps/ArmourSheet/content.hbs deleted file mode 100644 index 83e1d44..0000000 --- a/templates/Apps/ArmourSheet/content.hbs +++ /dev/null @@ -1,140 +0,0 @@ -
-
- - - - - {{#if meta.embedded}} - - - {{/if}} - - - {{ rc-i18n "RipCrypt.common.cost" }} - -
- - - - - - -
-
-
-
-
- - {{ rc-i18n "RipCrypt.common.location" }} - - -
- -
-
- -
-
- -
-
- -
-
- -
-
diff --git a/templates/Apps/ArmourSheet/style.css b/templates/Apps/ArmourSheet/style.css deleted file mode 100644 index 24535ce..0000000 --- a/templates/Apps/ArmourSheet/style.css +++ /dev/null @@ -1,135 +0,0 @@ -.ripcrypt.ArmourSheet > .window-content { - --input-height: 1rem; - --input-underline: none; - --col-gap: 8px; - --row-gap: 8px; - - --string-tags-tag-text: var(--header-text); - --string-tags-tag-background: var(--header-background); - --string-tags-add-text: white; - --string-tags-add-background: var(--accent-1); - --string-tags-input-text: white; - --string-tags-input-background: var(--accent-2); - - --input-text: white; - --input-background: var(--accent-2); - --button-text: white; - --button-background: var(--accent-2); - - --pill-width: 100%; - --pill-border-radius: 4px; - - display: flex; - flex-direction: column; - gap: 8px; - - padding: 8px; - background: var(--base-background); - color: var(--base-text); - - hr { - background: var(--accent-1); - grid-column: 1 / -1; - height: 1px; - width: 90%; - margin: 0 auto; - - &.vertical { - grid-column: unset; - height: 100%; - } - } - - label, .label { - display: flex; - align-items: center; - box-sizing: border-box; - - padding: 2px 4px; - text-transform: uppercase; - font-size: var(--font-size-14); - overflow: hidden; - text-overflow: ellipsis; - font-weight: bold; - } - - button, input, select, .value { - border-radius: 4px; - padding: 2px 4px; - } - input[type="checkbox"] { - justify-self: end; - padding: 0; - } - .value { - border: 2px solid var(--accent-2); - } - - .contents { - display: grid; - grid-template-columns: 300px 1px 118px; - gap: 8px; - - > .contents__left { - display: grid; - grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); - column-gap: var(--col-gap); - row-gap: var(--row-gap); - } - - > .contents__right { - display: flex; - flex-direction: column; - gap: 8px; - } - } - - .section-pill { - background: var(--section-header-background); - color: var(--section-header-text); - padding: 0 4px; - border-radius: 999px; - text-align: right; - } - - rc-border { - grid-column: 1 / -1; - - > .content { - display: grid; - grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); - column-gap: var(--col-gap); - row-gap: var(--row-gap); - } - - .label { - background: purple; - } - } - - .center { - text-align: center; - } - - .compass { - --size: 35px; - width: var(--size); - height: var(--size); - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - border: 2px solid var(--accent-1); - border-radius: 50%; - font-size: 1.1rem; - position: relative; - background: var(--base-background); - - > .value { - background: none; - width: 70%; - text-align: center; - padding: 0; - } - } -} diff --git a/templates/Apps/CombinedHeroSheet/crafts.css b/templates/Apps/CombinedHeroSheet/crafts.css deleted file mode 100644 index 3e803da..0000000 --- a/templates/Apps/CombinedHeroSheet/crafts.css +++ /dev/null @@ -1,38 +0,0 @@ -.ripcrypt.ripcrypt--CombinedHeroSheet .crafts-summary { - display: grid; - column-gap: var(--col-gap); - grid-template-columns: repeat(3, minmax(0, 3fr)); - grid-template-rows: repeat(5, minmax(0, 1fr)); - grid-auto-flow: column; - padding: 8px; - - .col-header { - background: var(--section-header-background); - color: var(--section-header-text); - border-radius: 999px; - } - - label, .label { - box-sizing: border-box; - padding: 2px 4px; - text-transform: uppercase; - font-size: var(--font-size-14); - overflow: hidden; - text-overflow: ellipsis; - font-weight: bold; - } - - .craft-list { - grid-row: span 4; - display: contents; - - > :nth-child(odd) { - background: var(--alt-row-background); - color: var(--alt-row-text); - } - } - - span.name { - flex-grow: 1; - } -} diff --git a/templates/Apps/CombinedHeroSheet/crafts.hbs b/templates/Apps/CombinedHeroSheet/crafts.hbs deleted file mode 100644 index e0c08ab..0000000 --- a/templates/Apps/CombinedHeroSheet/crafts.hbs +++ /dev/null @@ -1,67 +0,0 @@ -
-
Focus
-
    - {{#each craft.focus as | craft |}} - {{#if craft}} -
  1. - {{ craft.name }} - {{#if craft.use}} - - {{/if}} -
  2. - {{else}} -
  3. - {{/if}} - {{/each}} -
- -
Fract
-
    - {{#each craft.fract as | craft |}} - {{#if craft}} -
  1. - {{ craft.name }} - {{#if craft.use}} - - {{/if}} -
  2. - {{else}} -
  3. - {{/if}} - {{/each}} -
- -
Flect
-
    - {{#each craft.flect as | craft |}} - {{#if craft}} -
  1. - {{ craft.name }} - {{#if craft.use}} - - {{/if}} -
  2. - {{else}} -
  3. - {{/if}} - {{/each}} -
-
diff --git a/templates/Apps/CombinedHeroSheet/style.css b/templates/Apps/CombinedHeroSheet/style.css deleted file mode 100644 index c458b72..0000000 --- a/templates/Apps/CombinedHeroSheet/style.css +++ /dev/null @@ -1,13 +0,0 @@ -@import url("./crafts.css"); - -.ripcrypt.ripcrypt--CombinedHeroSheet { - > .window-content { - gap: 4px; - background: var(--base-background); - overflow-y: auto; - } - - .HeroSkillsCardV1 { - --col-gap: 2px; - } -} diff --git a/templates/Apps/CraftCardV1/content.hbs b/templates/Apps/CraftCardV1/content.hbs deleted file mode 100644 index d5d10ed..0000000 --- a/templates/Apps/CraftCardV1/content.hbs +++ /dev/null @@ -1,101 +0,0 @@ -
-
- {{rc-i18n "RipCrypt.common.glimcraft"}} -
-
-
10
-
8
-
6
-
4
- -
-
- -
- {{aura.normal}} - - {{aura.heavy}} -
-
-
-
- -
- {{rc-i18n "RipCrypt.common.aspectNames.focus"}} - {{rc-i18n "RipCrypt.common.details"}} -
-
    - {{#each craft.focus as | craft |}} - {{#if craft}} -
  1. - {{ craft.name }} - {{#if craft.use}} - - {{/if}} -
  2. - {{else}} -
  3. - {{/if}} - {{/each}} -
- -
- {{rc-i18n "RipCrypt.common.aspectNames.flect"}} - {{rc-i18n "RipCrypt.common.details"}} -
-
    - {{#each craft.flect as | craft |}} - {{#if craft}} -
  1. - {{ craft.name }} - {{#if craft.use}} - - {{/if}} -
  2. - {{else}} -
  3. - {{/if}} - {{/each}} -
- -
- {{rc-i18n "RipCrypt.common.aspectNames.fract"}} - {{rc-i18n "RipCrypt.common.details"}} -
-
    - {{#each craft.fract as | craft |}} - {{#if craft}} -
  1. - {{ craft.name }} - {{#if craft.use}} - - {{/if}} -
  2. - {{else}} -
  3. - {{/if}} - {{/each}} -
-
diff --git a/templates/Apps/CraftCardV1/style.css b/templates/Apps/CraftCardV1/style.css deleted file mode 100644 index ae85b05..0000000 --- a/templates/Apps/CraftCardV1/style.css +++ /dev/null @@ -1,137 +0,0 @@ -.ripcrypt .CraftCardV1 { - --col-gap: 8px; - - display: grid; - column-gap: var(--col-gap); - grid-template-columns: repeat(2, minmax(0, 1fr)); - grid-template-rows: repeat(15, minmax(0, 1fr)); - - background: var(--base-background); - color: var(--base-text); - - .col-header { - display: flex; - flex-direction: row; - align-items: center; - background: var(--section-header-background); - color: var(--section-header-text); - padding: 2px 4px; - border-radius: 999px; - } - - label, .label { - box-sizing: border-box; - padding: 2px 4px; - text-transform: uppercase; - font-size: var(--font-size-14); - overflow: hidden; - text-overflow: ellipsis; - font-weight: bold; - } - - .aura-container { - grid-column: 1 / -1; - grid-row: 2 / span 4; - display: grid; - grid-template-columns: repeat(7, minmax(0, 1fr)); - grid-template-rows: minmax(0, 1fr); - position: relative; - } - - .circle-fragment, .full-circle { - display: flex; - justify-content: center; - align-items: center; - } - - .circle-fragment { - border-top-left-radius: 24% 100%; - border-bottom-left-radius: 25% 100%; - border-left: 2px dashed var(--accent-3); - margin-right: -5%; - } - - .full-circle { - border: 2px dashed var(--accent-3); - flex-grow: 0; - border-radius: 999px; - width: 80%; - aspect-ratio: 1; - align-self: center; - justify-self: center; - grid-row: 1; - grid-column: 4; - } - - .caster-silhouette { - grid-column: 4 / span 4; - grid-row: 1; - position: absolute; - left: 2rem; - width: 70%; - bottom: -10px; - } - - .aura-values { - grid-row: 1; - grid-column: -3 / -1; - display: flex; - justify-content: center; - align-items: center; - z-index: 3; - - .dual-pill { - border-radius: 999px; - background: var(--accent-1); - display: flex; - flex-direction: row; - gap: 0.25rem; - align-items: center; - padding-left: 8px; - margin-left: 1rem; - margin-bottom: 1.2rem; - } - - .values { - border-radius: 999px; - margin: 2px; - background: var(--base-background); - color: var(--base-text); - padding: 0.125rem 0.5rem; - display: flex; - flex-direction: row; - gap: 0.5rem; - --slash-color: var(--accent-1); - } - } - - .craft-list { - display: grid; - grid-template-rows: subgrid; - - > :nth-child(even) { - background: var(--alt-row-background); - color: var(--alt-row-text); - } - } - - span.name { - flex-grow: 1; - } - - [data-aspect="focus"] { --row: 6; --col: 1; } - [data-aspect="flect"] { --row: 6; --col: 2; } - [data-aspect="fract"] { --row: 11; --col: 1; } - - [data-aspect] { - &.aspect-header { - z-index: 1; - grid-row: var(--row); - grid-column: var(--col); - } - &.craft-list { - grid-row: calc(var(--row) + 1) / span 4; - grid-column: var(--col); - } - } -} diff --git a/templates/Apps/CryptApp/main.hbs b/templates/Apps/CryptApp/main.hbs new file mode 100644 index 0000000..80f0024 --- /dev/null +++ b/templates/Apps/CryptApp/main.hbs @@ -0,0 +1,3 @@ +
+ Hello +
\ No newline at end of file diff --git a/templates/Apps/DelveDiceHUD/difficulty.hbs b/templates/Apps/DelveDiceHUD/difficulty.hbs deleted file mode 100644 index bf5704f..0000000 --- a/templates/Apps/DelveDiceHUD/difficulty.hbs +++ /dev/null @@ -1,14 +0,0 @@ -
-
- {{dc}} - -
-
diff --git a/templates/Apps/DelveDiceHUD/fateCompass.hbs b/templates/Apps/DelveDiceHUD/fateCompass.hbs deleted file mode 100644 index 983e6bf..0000000 --- a/templates/Apps/DelveDiceHUD/fateCompass.hbs +++ /dev/null @@ -1,64 +0,0 @@ -
-
-
- - {{#if meta.editable}} - - - - - {{else}} - {{rc-i18n "RipCrypt.common.ordinals.North.abbv"}} - {{rc-i18n "RipCrypt.common.ordinals.West.abbv"}} - {{rc-i18n "RipCrypt.common.ordinals.East.abbv"}} - {{rc-i18n "RipCrypt.common.ordinals.South.abbv"}} - {{/if}} -
-
-
diff --git a/templates/Apps/DelveDiceHUD/style.css b/templates/Apps/DelveDiceHUD/style.css deleted file mode 100644 index 55128c2..0000000 --- a/templates/Apps/DelveDiceHUD/style.css +++ /dev/null @@ -1,88 +0,0 @@ -#ripcrypt-delve-dice { - display: grid; - grid-template-columns: max-content 2rem 90px 2rem max-content; - gap: 8px; - padding: 4px 1.5rem; - background: var(--DelveDice-background); - align-items: center; - justify-items: center; - pointer-events: all; - - border-radius: 0 0 999px 999px; - - button { - &:hover { - cursor: pointer; - } - } - - #fate-compass { - width: 100%; - height: 100%; - overflow: visible; - position: relative; - - .compass-container { - position: absolute; - background: var(--DelveDice-background); - border-radius: 0 0 999px 999px; - padding: 4px; - width: 100%; - } - - .compass { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - grid-template-rows: repeat(3, minmax(0, 1fr)); - grid-template-areas: - ". N ." - "W A E" - ". S ."; - align-items: center; - justify-items: center; - background: var(--accent-2); - border-radius: 999px; - aspect-ratio: 1; - } - - .compass-pointer { - grid-area: A; - transition: 500ms transform; - transform: rotate(-90deg); /* North by default */ - } - } - - #the-hourglass, - #delve-difficulty { - width: 100%; - height: 100%; - display: flex; - flex-direction: row; - position: relative; - - .icon-container { - position: absolute; - width: 34px; - display: grid; - padding: 4px 0; - background: var(--accent-1); - border-radius: 8px; - - > * { - grid-row: 1 / -1; - grid-column: 1 / -1; - } - - span { - font-size: 1.25rem; - z-index: 2; - align-self: center; - justify-self: center; - } - - rc-svg { - inset: 4px; - } - } - } -} diff --git a/templates/Apps/DelveDiceHUD/tour/current.hbs b/templates/Apps/DelveDiceHUD/tour/current.hbs deleted file mode 100644 index 8c802ce..0000000 --- a/templates/Apps/DelveDiceHUD/tour/current.hbs +++ /dev/null @@ -1,16 +0,0 @@ -
-
- - {{sandsOfFate}} - - -
-
diff --git a/templates/Apps/DelveDiceHUD/tour/next.hbs b/templates/Apps/DelveDiceHUD/tour/next.hbs deleted file mode 100644 index 5e102f0..0000000 --- a/templates/Apps/DelveDiceHUD/tour/next.hbs +++ /dev/null @@ -1,22 +0,0 @@ -
- {{#if meta.editable}} - - {{else}} - {{!-- This is here to prevent height collapsing --}} - ​ - {{/if}} -
diff --git a/templates/Apps/DelveDiceHUD/tour/previous.hbs b/templates/Apps/DelveDiceHUD/tour/previous.hbs deleted file mode 100644 index b8c59b7..0000000 --- a/templates/Apps/DelveDiceHUD/tour/previous.hbs +++ /dev/null @@ -1,23 +0,0 @@ -
- {{#if meta.editable}} - - {{else}} - {{!-- This is here to prevent height collapsing --}} - ​ - {{/if}} -
- diff --git a/templates/Apps/DicePool/buttons.hbs b/templates/Apps/DicePool/buttons.hbs deleted file mode 100644 index 0dc1b00..0000000 --- a/templates/Apps/DicePool/buttons.hbs +++ /dev/null @@ -1,8 +0,0 @@ -
- -
diff --git a/templates/Apps/DicePool/drag.hbs b/templates/Apps/DicePool/drag.hbs deleted file mode 100644 index 11f1974..0000000 --- a/templates/Apps/DicePool/drag.hbs +++ /dev/null @@ -1,28 +0,0 @@ -
- -
- {{ rc-i18n "RipCrypt.common.drag" }} -
-
- - {{drag}} - -
-
-
diff --git a/templates/Apps/DicePool/edge.hbs b/templates/Apps/DicePool/edge.hbs deleted file mode 100644 index f119224..0000000 --- a/templates/Apps/DicePool/edge.hbs +++ /dev/null @@ -1,28 +0,0 @@ -
- -
- {{ rc-i18n "RipCrypt.common.edge" }} -
-
- - {{edge}} - -
-
-
diff --git a/templates/Apps/DicePool/numberOfDice.hbs b/templates/Apps/DicePool/numberOfDice.hbs deleted file mode 100644 index b3983b9..0000000 --- a/templates/Apps/DicePool/numberOfDice.hbs +++ /dev/null @@ -1,33 +0,0 @@ - -
- {{ rc-i18n "RipCrypt.Apps.numberOfDice" }} -
-
- -
- - {{ numberOfDice }} -
- -
-
diff --git a/templates/Apps/DicePool/style.css b/templates/Apps/DicePool/style.css deleted file mode 100644 index e09628c..0000000 --- a/templates/Apps/DicePool/style.css +++ /dev/null @@ -1,73 +0,0 @@ -.ripcrypt.ripcrypt--DicePool { - > .window-content { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - grid-template-rows: auto min-content; - background: var(--base-background); - padding: 8px; - gap: 8px; - width: 250px; - } - - --button-background: var(--alt-row-background); - --button-text: var(--alt-row-text); - button { - border-radius: 2px; - font-weight: bold; - padding: 4px 8px; - width: max-content; - } - - .d8-incrementer { - display: flex; - flex-direction: column; - align-items: center; - gap: 4px; - - button { - width: max-content; - } - } - - .dice-count-row { - display: flex; - flex-direction: row; - flex-wrap: nowrap; - justify-content: center; - align-items: center; - gap: 4px; - font-size: 1.5rem; - } - - .dredge-row { - display: flex; - gap: 8px; - align-items: center; - } - - .dice-target { - display: flex; - position: relative; - - .value { - position: absolute; - inset: 0; - display: flex; - justify-content: center; - align-items: center; - font-size: 1.5rem; - color: white; - font-weight: normal; - } - } - - .button-row { - --button-background: var(--header-background); - --button-text: var(--header-text); - - display: flex; - justify-content: center; - align-items: center; - grid-column: 1 / -1; - } -} diff --git a/templates/Apps/DicePool/target.hbs b/templates/Apps/DicePool/target.hbs deleted file mode 100644 index 2a6e498..0000000 --- a/templates/Apps/DicePool/target.hbs +++ /dev/null @@ -1,32 +0,0 @@ - -
Target
-
- -
- -
{{target}}
-
- -
-
diff --git a/templates/Apps/HeroSkillsCardV1/content.hbs b/templates/Apps/HeroSkillsCardV1/content.hbs new file mode 100644 index 0000000..3f6db8d --- /dev/null +++ b/templates/Apps/HeroSkillsCardV1/content.hbs @@ -0,0 +1,109 @@ +
+
+ {{ rc-i18n "RipCrypt.Apps.grit-skills" }} + {{ rc-i18n "RipCrypt.common.rank" }} +
+
    +
  1. +
  2. +
  3. +
  4. +
+ +
+ {{ rc-i18n "RipCrypt.Apps.gait-skills" }} + {{ rc-i18n "RipCrypt.common.rank" }} +
+
    +
  1. +
  2. +
  3. +
  4. +
+ +
+ {{ rc-i18n "RipCrypt.Apps.grip-skills" }} + {{ rc-i18n "RipCrypt.common.rank" }} +
+
    +
  1. +
  2. +
  3. +
  4. +
+ +
+ {{ rc-i18n "RipCrypt.Apps.glim-skills" }} + {{ rc-i18n "RipCrypt.common.rank" }} +
+
    +
  1. +
  2. +
  3. +
  4. +
+ +
+ {{ rc-i18n "RipCrypt.common.gear" }} + {{ rc-i18n "RipCrypt.common.slot" }} +
+
    +
  1. +
  2. +
  3. +
  4. +
  5. +
  6. +
  7. +
  8. +
  9. +
  10. +
  11. +
  12. +
+ +
+
+ <{{{ifThen meta.editable "label" "div" }}} + for="{{meta.idp}}-gold" + class="label" + > + {{ rc-i18n "RipCrypt.common.currency.gold"}} + + +
+
+ <{{{ifThen meta.editable "label" "div" }}} + for="{{meta.idp}}-silver" + class="label" + > + {{ rc-i18n "RipCrypt.common.currency.silver"}} + + +
+
+ <{{{ifThen meta.editable "label" "div" }}} + for="{{meta.idp}}-copper" + class="label" + > + {{ rc-i18n "RipCrypt.common.currency.copper"}} + + +
+
+
\ No newline at end of file diff --git a/templates/Apps/HeroSkillsCardV1/style.css b/templates/Apps/HeroSkillsCardV1/style.css new file mode 100644 index 0000000..e4c935d --- /dev/null +++ b/templates/Apps/HeroSkillsCardV1/style.css @@ -0,0 +1,121 @@ +.ripcrypt .HeroSkillsCardV1 { + + /* Foundry Variable Tweaks */ + --input-height: 1rem; + --col-gap: 8px; + + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + grid-template-rows: repeat(13, minmax(0, 1fr)); + column-gap: var(--col-gap); + + background: var(--base-background); + color: var(--base-text); + + .col-header { + background: var(--section-header-background); + color: var(--section-header-text); + } + .row-alt { + background: var(--alt-row-background); + color: var(--alt-row-text); + } + + label, .label { + box-sizing: border-box; + padding: 2px 4px; + text-transform: uppercase; + font-size: var(--font-size-14); + overflow: hidden; + text-overflow: ellipsis; + font-weight: bold; + } + + .list-header { + display: flex; + justify-content: space-between; + align-items: center; + } + .skill-list { + display: grid; + grid-template-rows: subgrid; + + & > li { + padding-left: 4px; + } + + &.even > :nth-child(even), + &.odd > :nth-child(odd) { + background: var(--alt-row-background); + color: var(--alt-row-text); + } + } + + .grit-skills { + grid-column: 1 / span 1; + grid-row: 2 / span 4; + } + + .gait-skills { + grid-column: 2 / span 1; + grid-row: 2 / span 4; + } + + .grip-skills-header { + grid-column: 1 / span 1; + grid-row: 6 / span 1; + } + .grip-skills { + grid-column: 1 / span 1; + grid-row: 7 / span 4; + } + + .glim-skills-header { + grid-column: 2 / span 1; + grid-row: 6 / span 1; + } + .glim-skills { + grid-column: 2 / span 1; + grid-row: 7 / span 4; + } + + .gear-list { + grid-row: span 12; + display: grid; + grid-template-rows: subgrid; + list-style-type: none; + + > :nth-child(even) { + background: var(--alt-row-background); + color: var(--alt-row-text); + } + } + + .currencies { + grid-column: 1 / span 2; + grid-row: 13 / span 1; + display: grid; + column-gap: var(--col-gap); + grid-template-columns: repeat(3, minmax(0, 1fr)); + + .currency { + display: grid; + grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); + align-items: center; + background: var(--section-header-background); + color: var(--section-header-text); + --input-background: var(--base-background); + --input-text: var(--base-text); + + .input { + margin: 2px; + border-radius: 999px; + text-align: center; + } + } + } + + .half-pill { + border-radius: 0 999px 999px 0; + } +} diff --git a/templates/Apps/StatsCardV1/content.hbs b/templates/Apps/HeroSummaryCardV1/content.hbs similarity index 52% rename from templates/Apps/StatsCardV1/content.hbs rename to templates/Apps/HeroSummaryCardV1/content.hbs index d4c75e2..9fa9812 100644 --- a/templates/Apps/StatsCardV1/content.hbs +++ b/templates/Apps/HeroSummaryCardV1/content.hbs @@ -1,10 +1,13 @@ -
+
{{!-- * Header --}}
Logo Image
-
-
- -
{{!-- * Armour --}} -
-
- {{ rc-i18n "RipCrypt.common.armour" }} -
-
- {{#if (eq actor.type "hero")}} - - {{else}} - - {{/if}} - {{#each armours as | slot |}} -
-
- - {{ slot.defense }} - - {{#if slot.shielded}} - - {{/if}} -
- {{ rc-i18n (concat "RipCrypt.common.anatomy." @key) }} -
- {{/each}} -
-
    -
  • - {{ rc-i18n "RipCrypt.common.anatomy.head" }} - {{ armours.head.name }} -
  • -
  • - {{ rc-i18n "RipCrypt.common.anatomy.body" }} - {{ armours.body.name }} -
  • -
  • - {{ rc-i18n "RipCrypt.common.anatomy.arms" }} - {{ armours.arms.name }} -
  • -
  • - {{ rc-i18n "RipCrypt.common.anatomy.legs" }} - {{ armours.legs.name }} -
  • -
  • - {{ rc-i18n "RipCrypt.common.shield" }} - {{ shield.name }} -
  • -
-
+
{{!-- * Fate & Advancement --}}
- + - {{ rc-options level.rank.selected level.rank.options localize=true }} + {{ rc-options level.rank.selected level.rank.options }} {{else}}
- - {{ rc-i18n "RipCrypt.common.weapon.singular" }} - - + {{ rc-i18n "RipCrypt.common.weapon.plural" }} {{ rc-i18n "RipCrypt.Apps.traits-range" }} {{ rc-i18n "RipCrypt.common.wear" }} - {{ rc-i18n "RipCrypt.common.damage" }} + {{ rc-i18n "RipCrypt.common.damage" }} @@ -243,30 +133,14 @@ class="{{slot.class}}" aria-hidden="true" > - {{ rc-i18n "RipCrypt.common.empty" }} + {{ rc-i18n "RipCrypt.common.empty" }} + - {{else}} - - - {{!-- ? NOTE: Disabled for now to see what user feedback spawns - --}} - - {{ slot.data.quantifiedName }} - - + + {{ slot.data.name }} {{#if slot.data.system.traitString}} {{ slot.data.system.traitString }} @@ -278,7 +152,7 @@ {{ slot.data.system.wear.value }} / {{ slot.data.system.wear.max }} - + {{ slot.data.system.damage }} @@ -310,8 +184,8 @@ type="button" class="roll icon" data-action="roll" - data-dice-count="{{ability.value}}" - data-flavor="{{ability.name}} Roll" + data-formula="{{ability.value}}d8rc4" + data-flavor="{{ability.name}} Roll (Difficulty: 4)" > {{#unless ability.readonly}} {{else}} -
+
{{ ability.name }}
{{/unless}} @@ -382,8 +256,8 @@ {{speed.move}} {{speed.run}}
-
diff --git a/templates/Apps/StatsCardV1/style.css b/templates/Apps/HeroSummaryCardV1/style.css similarity index 64% rename from templates/Apps/StatsCardV1/style.css rename to templates/Apps/HeroSummaryCardV1/style.css index 13092a8..8d23752 100644 --- a/templates/Apps/StatsCardV1/style.css +++ b/templates/Apps/HeroSummaryCardV1/style.css @@ -1,4 +1,4 @@ -.ripcrypt .StatsCardV1 { +.ripcrypt .HeroSummaryCardV1 { /* Foundry Variable Tweaks */ --input-height: 1rem; @@ -12,10 +12,6 @@ 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); } @@ -28,6 +24,7 @@ box-sizing: border-box; padding: 2px 4px; text-transform: uppercase; + font-size: var(--font-size-14); overflow: hidden; text-overflow: ellipsis; font-weight: bold; @@ -53,13 +50,6 @@ 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; @@ -94,28 +84,20 @@ display: grid; grid-template-rows: subgrid; } - .fate-value { - padding-left: 2px; - } .weapons { grid-column: 1 / span 4; grid-row: 7 / span 5; display: grid; grid-template-columns: subgrid; - grid-template-rows: subgrid; + grid-auto-rows: min-content; + overflow-y: auto; thead, tbody, tr { display: contents; } - td { - display: flex; - flex-direction: row; - align-items: center; - gap: 4px; - } .row-alt > * { background: inherit; } @@ -139,10 +121,7 @@ label, .label { width: 100%; - height: 100%; - display: flex; - justify-content: center; - align-items: center; + text-align: center; } } @@ -158,7 +137,6 @@ border-radius: 50%; font-size: 1.5rem; position: relative; - background: var(--base-background); > .value { background: none; @@ -175,11 +153,6 @@ z-index: 2; } - &.small { - --size: 35px; - font-size: 1.1rem; - } - &.dual { font-size: var(--font-size-14); --distance-from-edge: 4px; @@ -212,74 +185,4 @@ } } } - - .armour { - grid-column: -2 / span 1; - grid-row: 1 / -1; - display: grid; - grid-template-rows: subgrid; - - .section-header { - text-align: right; - } - - .person { - grid-row: 2 / span 9; - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - grid-template-rows: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.2fr); - justify-items: center; - align-items: center; - position: relative; - - > div { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - z-index: 1; - } - - > rc-svg { - position: absolute; - bottom: 0; - left: 0; - width: 58%; - } - } - - /* Positioning */ - .head, .body, .legs { grid-column: 1; } - .arms { grid-column: 2; } - .head { grid-row: 1; } - .body, .arms { grid-row: 2; } - .legs { grid-row: 3; } - - .shield { - --distance: -7px; - position: absolute; - top: var(--distance); - right: var(--distance); - } - - .armour-items { - display: contents; - - > li { - display: flex; - flex-direction: row-reverse; - justify-content: space-between; - align-items: center; - flex-wrap: nowrap; - padding: 0 4px; - gap: 4px; - min-width: 0; - } - - .label { - text-overflow: initial; - flex-shrink: 0; - } - } - } } diff --git a/templates/Apps/RichEditor/content.hbs b/templates/Apps/RichEditor/content.hbs deleted file mode 100644 index 3b203dd..0000000 --- a/templates/Apps/RichEditor/content.hbs +++ /dev/null @@ -1,21 +0,0 @@ -
- {{#if editable}} - {{#if (not collaborative)}} -

- {{ rc-i18n "RipCrypt.Apps.RichEditor-no-collaborative" }} -

- {{/if}} - - {{{ enriched }}} - - {{else}} - {{{ enriched }}} - {{/if}} -
diff --git a/templates/Apps/RichEditor/style.css b/templates/Apps/RichEditor/style.css deleted file mode 100644 index 70f6270..0000000 --- a/templates/Apps/RichEditor/style.css +++ /dev/null @@ -1,19 +0,0 @@ -.ripcrypt--RichEditor { - width: 500px; - height: 600px; - - > .window-content { - padding: 4px; - background: var(--base-background); - height: 100%; - } - - prose-mirror { - height: 100%; - - .editor-content { - color: var(--input-text); - background: var(--input-background); - } - } -} diff --git a/templates/Apps/SkillsCardV1/content.hbs b/templates/Apps/SkillsCardV1/content.hbs deleted file mode 100644 index 231e388..0000000 --- a/templates/Apps/SkillsCardV1/content.hbs +++ /dev/null @@ -1,269 +0,0 @@ -
-
- {{ rc-i18n "RipCrypt.Apps.grit-skills" }} - -
-
    - {{#each skills.grit as | skill |}} - {{#if skill}} -
  1. - {{ skill.name }} - -
  2. - {{else}} -
  3. - {{/if}} - {{/each}} -
- -
- {{ rc-i18n "RipCrypt.Apps.gait-skills" }} - -
-
    - {{#each skills.gait as | skill |}} - {{#if skill}} -
  1. - {{ skill.name }} - -
  2. - {{else}} -
  3. - {{/if}} - {{/each}} -
- -
- {{ rc-i18n "RipCrypt.Apps.grip-skills" }} - -
-
    - {{#each skills.grip as | skill |}} - {{#if skill}} -
  1. - {{ skill.name }} - -
  2. - {{else}} -
  3. - {{/if}} - {{/each}} -
- -
- {{ rc-i18n "RipCrypt.Apps.glim-skills" }} - -
-
    - {{#each skills.glim as | skill |}} - {{#if skill}} -
  1. - {{ skill.name }} - -
  2. - {{else}} -
  3. - {{/if}} - {{/each}} -
- -
- {{ rc-i18n "RipCrypt.common.gear" }} - -
- {{ rc-i18n "RipCrypt.common.slot" }} -
-
    - {{#each gear as | itemInSlot |}} -
  1. - {{itemInSlot.name}} -
  2. - {{/each}} -
- - {{!-- * Currencies --}} -
-
- - -
-
- - -
-
- - -
-
- - {{!-- * Ammo Summary & Stars --}} -
    -
  • -
    - -
    - {{ rc-i18n "RipCrypt.common.ammo"}} -
    -
    - {{ ammo }} -
    -
    -
  • - {{#each favouriteAmmo as | data |}} -
  • - {{#if data}} -
    -
    - {{data.name}} -
    - -
    - {{else}} -
    - {{ rc-i18n "RipCrypt.Apps.starred-ammo-placeholder" }} -
    - {{/if}} -
  • - {{/each}} -
- - {{!-- * Aura Size --}} - {{#if aura}} -
- -
- {{aura.normal}} - - {{aura.heavy}} -
-
- {{/if}} -
diff --git a/templates/Apps/SkillsCardV1/style.css b/templates/Apps/SkillsCardV1/style.css deleted file mode 100644 index c1815ce..0000000 --- a/templates/Apps/SkillsCardV1/style.css +++ /dev/null @@ -1,182 +0,0 @@ -.ripcrypt .SkillsCardV1 { - - /* Foundry Variable Tweaks */ - --input-height: 1rem; - --col-gap: 8px; - - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - grid-template-rows: repeat(14, minmax(0, 1fr)); - column-gap: var(--col-gap); - row-gap: var(--row-gap); - - background: var(--base-background); - color: var(--base-text); - - .col-header { - background: var(--section-header-background); - color: var(--section-header-text); - } - .row-alt { - background: var(--alt-row-background); - color: var(--alt-row-text); - } - - label, .label { - box-sizing: border-box; - padding: 2px 4px; - text-transform: uppercase; - font-size: var(--font-size-14); - overflow: hidden; - text-overflow: ellipsis; - font-weight: bold; - } - - .list-header { - display: flex; - gap: 4px; - align-items: center; - border-radius: 999px; - } - .skill-list { - display: grid; - grid-template-rows: subgrid; - - & > li { - padding: 0 4px; - .name { - flex-grow: 1; - } - } - - &.even > :nth-child(even), - &.odd > :nth-child(odd) { - background: var(--alt-row-background); - color: var(--alt-row-text); - } - } - - .grit-skills { - grid-column: 1 / span 1; - grid-row: 2 / span 4; - } - - .gait-skills { - grid-column: 2 / span 1; - grid-row: 2 / span 4; - } - - .grip-skills-header { - grid-column: 1 / span 1; - grid-row: 7 / span 1; - } - .grip-skills { - grid-column: 1 / span 1; - grid-row: 8 / span 4; - } - - .glim-skills-header { - grid-column: 2 / span 1; - grid-row: 7 / span 1; - } - .glim-skills { - grid-column: 2 / span 1; - grid-row: 8 / span 4; - } - - .gear-list { - grid-row: span 12; - display: grid; - grid-template-rows: subgrid; - list-style-type: none; - - > li { - padding: 0 4px; - } - - > :nth-child(even) { - background: var(--alt-row-background); - color: var(--alt-row-text); - } - } - - .ammo-list { - grid-column: 1 / span 2; - grid-row: 13 / span 2; - display: grid; - grid-template-columns: subgrid; - grid-template-rows: subgrid; - list-style-type: none; - padding: 0; - } - - .currencies { - grid-column: 1 / span 2; - grid-row: 12 / span 1; - display: grid; - column-gap: var(--col-gap); - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - - .aura-size { - grid-column: 3; - grid-row: 14; - } - - .pill { - display: grid; - grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); - align-items: center; - background: var(--section-header-background); - border-radius: 999px; - color: var(--section-header-text); - padding: 2px 0 2px 4px; - --input-background: var(--base-background); - --input-text: var(--base-text); - - &.with-icon { - grid-template-columns: min-content minmax(0, 1.5fr) minmax(0, 1fr); - gap: 4px; - } - - label, .label { - padding: 0; - white-space: nowrap; - text-overflow: ellipsis; - } - - input, .input { - margin: 0 2px 0 0; - border-radius: 999px; - text-align: center; - } - } - - .dual-pill { - border-radius: 999px; - background: var(--accent-1); - display: grid; - grid-template-columns: 2fr 1fr; - gap: 0.25rem; - align-items: center; - padding-left: 8px; - - .values { - border-radius: 999px; - margin: 2px; - background: var(--base-background); - color: var(--base-text); - padding: 0.125rem 0.5rem; - display: flex; - flex-direction: row; - justify-content: space-evenly; - gap: 0.5rem; - --slash-color: var(--accent-1); - } - - .value { - flex-grow: 1; - text-align: center; - } - } -} diff --git a/templates/Apps/apps.css b/templates/Apps/apps.css index db88f7e..5fee16a 100644 --- a/templates/Apps/apps.css +++ b/templates/Apps/apps.css @@ -1,30 +1,2 @@ -@import url("./AllItemSheetV1/style.css"); -@import url("./CombinedHeroSheet/style.css"); -@import url("./DelveDiceHUD/style.css"); -@import url("./DicePool/style.css"); -@import url("./CraftCardV1/style.css"); -@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"); - -.ripcrypt { - .window-content { - flex: initial; - padding: 0; - margin: 0; - } - - .StatsCardV1, - .SkillsCardV1, - .CraftCardV1 { - padding: 8px; - /* height: 270px; */ - width: 680px; - --col-gap: 2px; - --row-gap: 4px; - } -} +@import url("./HeroSummaryCardV1/style.css"); +@import url("./HeroSkillsCardV1/style.css"); diff --git a/templates/Apps/partials/item-header.hbs b/templates/Apps/partials/item-header.hbs deleted file mode 100644 index 300c166..0000000 --- a/templates/Apps/partials/item-header.hbs +++ /dev/null @@ -1,28 +0,0 @@ -{{!-- -Required parameters: - "name" : the name of the item - "system.quantity" : the quantity of the item - "meta.idp" : the ID Prefix for the application ---}} -
-
- - - -
-
diff --git a/templates/Apps/popover.css b/templates/Apps/popover.css deleted file mode 100644 index 73cfe4a..0000000 --- a/templates/Apps/popover.css +++ /dev/null @@ -1,17 +0,0 @@ -.ripcrypt.popover { - box-sizing: border-box; - - &.frameless { - border-width: 2px; - border-style: solid; - border-color: transparent; - border-radius: 4px; - position: absolute; - z-index: calc(var(--z-index-tooltip) - 5); - transform-origin: top left; - - &.locked { - border-color: var(--accent-3); - } - } -} diff --git a/templates/Apps/popovers/AmmoTracker/ammoList.hbs b/templates/Apps/popovers/AmmoTracker/ammoList.hbs deleted file mode 100644 index de799b2..0000000 --- a/templates/Apps/popovers/AmmoTracker/ammoList.hbs +++ /dev/null @@ -1,52 +0,0 @@ -
- {{#if ammos}} -
    - {{#each ammos as | data |}} -
  • - {{ data.ammo.name }} - - {{#if data.favourite}} - - {{else}} - - {{/if}} -
  • - {{/each}} -
- {{else}} - - {{ rc-i18n "RipCrypt.Apps.AmmoTracker.no-ammo" }} - - {{/if}} -
diff --git a/templates/Apps/popovers/AmmoTracker/style.css b/templates/Apps/popovers/AmmoTracker/style.css deleted file mode 100644 index 2425a5a..0000000 --- a/templates/Apps/popovers/AmmoTracker/style.css +++ /dev/null @@ -1,47 +0,0 @@ -.ripcrypt--AmmoTracker.ripcrypt--AmmoTracker.ripcrypt--AmmoTracker { - color: var(--popover-text); - background: var(--popover-background); - padding: 4px; - - --row-gap: 4px; - --button-text: var(--header-text); - --button-background: var(--header-background); - - ul { - display: flex; - flex-direction: column; - row-gap: var(--row-gap); - - > li { - padding: 4px 8px; - border-radius: 999px; - - &:nth-child(even) { - color: var(--popover-alt-row-text); - background: var(--popover-alt-row-background); - --input-text: var(--popover-text); - --input-background: var(--popover-background); - --button-text: unset; - --button-background: unset; - } - } - } - - .ammo { - display: grid; - grid-template-columns: 130px 50px min-content; - grid-template-rows: min-content; - align-items: center; - gap: 8px; - - .name { - flex-grow: 1; - justify-self: left; - } - } - - input { - text-align: center; - border-radius: 999px; - } -} diff --git a/templates/chat/frame.hbs b/templates/chat/frame.hbs new file mode 100644 index 0000000..9a0ba23 --- /dev/null +++ b/templates/chat/frame.hbs @@ -0,0 +1,7 @@ +
  • + {{ alias }} +
  • \ No newline at end of file diff --git a/templates/components/armour-summary.hbs b/templates/components/armour-summary.hbs deleted file mode 100644 index b0f01a4..0000000 --- a/templates/components/armour-summary.hbs +++ /dev/null @@ -1,35 +0,0 @@ -{{#if (eq type "hero")}} - -{{else}} - -{{/if}} -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    diff --git a/templates/css/chatmessage.css b/templates/css/chatmessage.css new file mode 100644 index 0000000..05014b9 --- /dev/null +++ b/templates/css/chatmessage.css @@ -0,0 +1,15 @@ +.ripcrypt.chat-message { + position: relative; + background: var(--base-background); + color: var(--base-text); + + .author { + position: absolute; + text-align: center; + top: 0; + left: 50%; + transform: translateY(-50%) translateX(-50%); + background: var(--title-background); + color: var(--title-text); + } +} diff --git a/templates/css/common.css b/templates/css/common.css new file mode 100644 index 0000000..37a4fee --- /dev/null +++ b/templates/css/common.css @@ -0,0 +1,28 @@ +@import url("./vars.css"); + +@import url("./elements/button.css"); +@import url("./elements/input.css"); +@import url("./elements/lists.css"); +@import url("./elements/select.css"); +@import url("./elements/span.css"); +@import url("./elements/table.css"); + +.ripcrypt { + .window-content { + padding: 0; + margin: 0; + } + + .HeroSummaryCardV1, + .HeroSkillsCardV1 { + /* height: 270px; */ + width: 680px; + --col-gap: 2px; + } + + label, input, select { + cursor: pointer; + } +} + +@import url("./chatmessage.css"); diff --git a/templates/css/components/armour-summary.css b/templates/css/components/armour-summary.css deleted file mode 100644 index fafb3a5..0000000 --- a/templates/css/components/armour-summary.css +++ /dev/null @@ -1,34 +0,0 @@ -:host { - display: inline-block; -} - -.person { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - grid-template-rows: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.2fr); - justify-items: center; - align-items: center; - position: relative; - row-gap: var(--row-gap); - - > div { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - z-index: 1; - } - - > rc-svg { - position: absolute; - bottom: 0; - left: 0; - width: 58%; - } - - .head, .body, .legs { grid-column: 1; } - .arms { grid-column: 2; } - .head { grid-row: 1; } - .body, .arms { grid-row: 2; } - .legs { grid-row: 3; } -} diff --git a/templates/css/components/icon.css b/templates/css/components/icon.css index 31ddda5..07b155c 100644 --- a/templates/css/components/icon.css +++ b/templates/css/components/icon.css @@ -14,10 +14,5 @@ svg { width: var(--size, 1rem); height: var(--size, 1rem); fill: var(--fill); -} - -path { stroke: var(--stroke); - stroke-width: var(--stroke-width); - stroke-linejoin: var(--stroke-linejoin); } diff --git a/templates/css/components/rc-border.css b/templates/css/components/rc-border.css deleted file mode 100644 index 3069d60..0000000 --- a/templates/css/components/rc-border.css +++ /dev/null @@ -1,65 +0,0 @@ -:host { - display: flex; - flex-direction: column; - --vertical-displacement: 12.5px; -} - -.rc-border { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - flex-grow: 1; - - padding: var(--padding, 4px); - border-width: 2px; - border-style: solid; - border-color: var(--border-color); - border-radius: 8px; - position: relative; - margin-top: var(--margin-top, var(--vertical-displacement)); - padding-top: var(--padding-top, calc(var(--vertical-displacement) + 4px)); - - &::before { - display: block; - content: ""; - position: absolute; - top: -3px; - height: 5px; - left: 50%; - right: -3px; - background: var(--border-mask, var(--base-background)); - } - &::after { - display: block; - content: ""; - position: absolute; - width: 6px; - top: -3px; - right: -3px; - height: 30px; - background: rgb(0,0,0); - background: linear-gradient( - 180deg, - var(--border-mask, var(--base-background)) 0%, - var(--border-mask, var(--base-background)) 50%, - rgba(0,255,255,0) 100% - ); - } - - .title { - position: absolute; - top: calc(-1 * var(--vertical-displacement)); - left: 50%; - height: minmax(var(--title-height, 20px), auto); - transform: translateX(-50%); - background: var(--title-background, var(--border-color)); - padding: 4px 6px; - box-sizing: border-box; - width: max-content; - max-width: 75%; - min-width: 50px; - border-radius: 4px; - text-align: center; - } -} diff --git a/templates/css/components/svg-loader.css b/templates/css/components/svg-loader.css deleted file mode 100644 index b843bc5..0000000 --- a/templates/css/components/svg-loader.css +++ /dev/null @@ -1,22 +0,0 @@ -:host { - display: inline-block; -} - -div { - display: flex; - justify-content: center; - align-items: center; - width: 100%; - height: 100%; -} - -svg { - fill: var(--fill); - stroke: var(--stroke); -} - -path { - stroke: var(--stroke); - stroke-width: var(--stroke-width); - stroke-linejoin: var(--stroke-linejoin); -} diff --git a/templates/css/elements/button.css b/templates/css/elements/button.css index 7ab1590..bcd0375 100644 --- a/templates/css/elements/button.css +++ b/templates/css/elements/button.css @@ -1,25 +1,9 @@ -.ripcrypt:where(.popover.frameless, .hud) button, .ripcrypt > .window-content button { - display: flex; - justify-content: center; - align-items: center; - outline: none; - border: none; + all: revert; padding: 2px 4px; - font-family: inherit; - font-size: inherit; background: var(--button-background); color: var(--button-text); - &:hover:not(:disabled) { - cursor: pointer; - outline: none; - } - - &:disabled { - opacity: 0.6; - } - &.icon { padding: 0; border-radius: 50%; @@ -27,11 +11,14 @@ border: none; width: 20px; height: 20px; - } - &.transparent { - background: inherit; - color: inherit; - padding: 0; + &:hover:not(:disabled) { + cursor: pointer; + outline: none; + } + + &:disabled { + opacity: 0.6; + } } } diff --git a/templates/css/elements/generic.css b/templates/css/elements/generic.css deleted file mode 100644 index 4b3115e..0000000 --- a/templates/css/elements/generic.css +++ /dev/null @@ -1,9 +0,0 @@ -.ripcrypt.popover.frameless, -.ripcrypt.hud, -.ripcrypt > .window-content { - .left-pill { border-radius: 999px 0 0 999px; } - .right-pill { border-radius: 0 999px 999px 0; } - .full-pill { border-radius: 999px; } - - .grow { flex-grow: 1; } -} diff --git a/templates/css/elements/input.css b/templates/css/elements/input.css index f7d60f8..0ab1fa0 100644 --- a/templates/css/elements/input.css +++ b/templates/css/elements/input.css @@ -1,7 +1,6 @@ -.ripcrypt.popover.frameless, -.ripcrypt.hud, .ripcrypt > .window-content { input, .input { + all: revert; box-sizing: border-box; border: none; outline: none; @@ -11,23 +10,10 @@ background: var(--input-background); color: var(--input-text); padding: 0px 4px; - cursor: pointer; &[type="text"], &[type="number"] { border-bottom: var(--input-underline); } - - &[type="checkbox"] { - all: revert-layer; - cursor: pointer; - --checkbox-checked-color: var(--accent-3); - --checkbox-background-color: var(--accent-2); - --checkbox-checkmark-color: black; - } - - &::placeholder { - color: var(--input-placeholder-text); - } } } diff --git a/templates/css/elements/lists.css b/templates/css/elements/lists.css index 24aa561..0f7b75d 100644 --- a/templates/css/elements/lists.css +++ b/templates/css/elements/lists.css @@ -1,5 +1,3 @@ -.ripcrypt.popover.frameless, -.ripcrypt.hud, .ripcrypt > .window-content { ol { list-style-type: none; @@ -9,14 +7,13 @@ > li { margin: 0; + padding: 2px 4px; display: flex; flex-direction: row; gap: 8px; align-items: center; counter-increment: list-index 1; position: relative; - padding: 0 4px; - border-radius: 999px; } &.num-before > li::before, @@ -34,13 +31,4 @@ right: 4px; } } - - ul { - margin: 0; - padding: 0; - - > li { - margin: 0; - } - } } diff --git a/templates/css/elements/p.css b/templates/css/elements/p.css deleted file mode 100644 index 91c29a1..0000000 --- a/templates/css/elements/p.css +++ /dev/null @@ -1,12 +0,0 @@ -.ripcrypt.popover.frameless p, -.ripcrypt.hud p, -.ripcrypt > .window-content p { - &.warning { - padding: 0.75rem; - margin: 0.25rem; - border-radius: 8px; - border-color: yellow; - border-style: solid; - border-width: 2px; - } -} diff --git a/templates/css/elements/pill-bar.css b/templates/css/elements/pill-bar.css deleted file mode 100644 index ec85807..0000000 --- a/templates/css/elements/pill-bar.css +++ /dev/null @@ -1,49 +0,0 @@ -.ripcrypt.popover.frameless .pill-bar, -.ripcrypt.hud .pill-bar, -.ripcrypt > .window-content .pill-bar { - display: flex; - flex-direction: row; - width: var(--pill-width, 100px); - border: 2px solid var(--pill-border); - border-radius: var(--pill-border-radius, 999px); - background: var(--pill-background); - align-items: center; - gap: 8px; - - > input { - color: var(--pill-input-text); - background: var(--pill-input-background); - border-radius: var(--pill-border-radius, 999px); - flex-shrink: 1; - flex-grow: 1; - min-width: 50px; - max-width: unset; - width: initial; - flex-basis: 50px; - text-align: center; - - &:disabled { - color: var(--pill-input-disabled-text); - background: var(--pill-input-disabled-background); - } - } - - > :first-child { - order: 1; - } - > :last-child { - order: 3; - } - - &::after { - display: block; - content: ""; - order: 1; - position: relative; - width: 2px; - height: 75%; - transform: rotate(30deg); - background: var(--pill-divider, var(--pill-border)); - z-index: 1; - } -} \ No newline at end of file diff --git a/templates/css/elements/prose-mirror.css b/templates/css/elements/prose-mirror.css deleted file mode 100644 index 7aaa978..0000000 --- a/templates/css/elements/prose-mirror.css +++ /dev/null @@ -1,3 +0,0 @@ -.ripcrypt prose-mirror * { - all: revert-layer; -} diff --git a/templates/css/elements/select.css b/templates/css/elements/select.css index 519c06e..2ea8495 100644 --- a/templates/css/elements/select.css +++ b/templates/css/elements/select.css @@ -1,6 +1,5 @@ -.ripcrypt.popover.frameless select, -.ripcrypt.hud select, .ripcrypt > .window-content select { + all: revert; appearance: auto; box-sizing: border-box; border: none; @@ -9,7 +8,4 @@ font-size: inherit; display: flex; align-items: center; - - background: var(--input-background); - color: var(--input-text); } diff --git a/templates/css/elements/span.css b/templates/css/elements/span.css index ef8bfa4..ac5b330 100644 --- a/templates/css/elements/span.css +++ b/templates/css/elements/span.css @@ -1,25 +1,5 @@ -.ripcrypt.popover.frameless span, -.ripcrypt.hud span, .ripcrypt > .window-content span { &.small { font-size: var(--font-size-10) } - - &.ellipses { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - } - - &.slash { - width: 2px; - background: var(--slash-color, currentColor); - border-radius: 999px; - transform: rotate(var(--slash-rotation, 15deg)); - } - - /* Makes it so that spans are never less than the font size */ - &:empty::before { - content: "\200b"; - } } diff --git a/templates/css/elements/string-tags.css b/templates/css/elements/string-tags.css deleted file mode 100644 index 1099982..0000000 --- a/templates/css/elements/string-tags.css +++ /dev/null @@ -1,36 +0,0 @@ -.ripcrypt string-tags { - --input-background: var(--string-tags-input-background); - - display: grid; - grid-template-columns: minmax(0, 1fr) min-content; - grid-template-rows: repeat(2, min-content); - - border: var(--string-tags-border); - - .tags { - grid-column: 1 / -1; - } - - input[type="text"] { - border-radius: 4px; - padding: 2px 4px; - } - - button.icon.icon { - font-family: var(--font-awesome); - background: var(--string-tags-add-background); - color: var(--string-tags-add-text); - width: 30px; - border-radius: 4px; - } - - &:has(.tags.input-element-tags:empty) { - grid-template-rows: auto; - } -} - -.ripcrypt .tag { - background: var(--tag-background, var(--header-background)); - color: var(--tag-text, var(--header-text)); - padding: 2px 4px; -} diff --git a/templates/css/elements/table.css b/templates/css/elements/table.css index fc44c35..d27d228 100644 --- a/templates/css/elements/table.css +++ b/templates/css/elements/table.css @@ -1,10 +1,14 @@ -.ripcrypt.popover.frameless table, -.ripcrypt.hud table, .ripcrypt > .window-content table { + all: revert; box-sizing: border-box; border-collapse: collapse; + thead, tbody, tr { + all: revert; + } + td, th { + all: revert; padding: 2px 4px; font-weight: initial; text-align: left; diff --git a/templates/css/main.css b/templates/css/main.css deleted file mode 100644 index a8c65a3..0000000 --- a/templates/css/main.css +++ /dev/null @@ -1,29 +0,0 @@ -@layer resets, themes, elements, partials, apps, exceptions; - -/* Resets */ -@import url("./resets/inputs.css") layer(resets); -@import url("./resets/tables.css") layer(resets); - -/* Themes */ -@import url("./themes/dark.css") layer(themes); - -/* Elements */ -@import url("./elements/generic.css") layer(elements); -@import url("./elements/button.css") layer(elements); -@import url("./elements/input.css") layer(elements); -@import url("./elements/lists.css") layer(elements); -@import url("./elements/p.css") layer(elements); -@import url("./elements/pill-bar.css") layer(elements); -@import url("./elements/select.css") layer(elements); -@import url("./elements/span.css") layer(elements); -@import url("./elements/string-tags.css") layer(elements); -@import url("./elements/table.css") layer(elements); - -/* Partials */ -@import url("./partials/item-header.css") layer(partials); - -/* Applications */ -@import url("../Apps/apps.css") layer(apps); - -/* Exceptions */ -@import url("./elements/prose-mirror.css") layer(exceptions); diff --git a/templates/css/partials/item-header.css b/templates/css/partials/item-header.css deleted file mode 100644 index 810c58f..0000000 --- a/templates/css/partials/item-header.css +++ /dev/null @@ -1,11 +0,0 @@ -.item-header { - .name-row { - display: grid; - grid-template-columns: minmax(0, 1fr) min-content 50px; - gap: 4px; - - .quantity { - text-align: center; - } - } -} diff --git a/templates/css/resets/inputs.css b/templates/css/resets/inputs.css deleted file mode 100644 index 3cb409b..0000000 --- a/templates/css/resets/inputs.css +++ /dev/null @@ -1,7 +0,0 @@ -.ripcrypt.hud, -.ripcrypt.popover.frameless, -.ripcrypt > .window-content { - button, input, select { - all: initial; - } -} diff --git a/templates/css/resets/tables.css b/templates/css/resets/tables.css deleted file mode 100644 index 1e4c53b..0000000 --- a/templates/css/resets/tables.css +++ /dev/null @@ -1,7 +0,0 @@ -.ripcrypt.hud, -.ripcrypt.popover.frameless, -.ripcrypt > .window-content { - table, thead, tbody, th, tr, td { - all: revert; - } -} diff --git a/templates/css/themes/dark.css b/templates/css/themes/dark.css index b454025..827c389 100644 --- a/templates/css/themes/dark.css +++ b/templates/css/themes/dark.css @@ -7,8 +7,8 @@ --base-text: white; --base-background: black; - --header-text: black; - --header-background: var(--accent-3); + --title-text: white; + --title-background: var(--accent-3); --section-header-text: white; --section-header-background: var(--accent-1); @@ -17,42 +17,9 @@ --alt-row-background: var(--accent-2); --input-underline: 2px dashed var(--accent-3); - --input-background: var(--accent-2); + --input-background: inherit; --input-text: white; - --input-placeholder-text: rgba(255,255,255, 0.5); --button-background: black; --button-text: var(--accent-3); - - --col-gap: 2px; - --row-gap: 0px; - - /* Popover Variables */ - --popover-text: var(--base-text); - --popover-background: var(--base-background); - - --popover-alt-row-text: var(--alt-row-text); - --popover-alt-row-background: var(--alt-row-background); - - --popover-header-text: var(--header-text); - --popover-header-background: var(--header-background); - - /* Additional Variables */ - --string-tags-border: inherit; - --string-tags-tag-background: inherit; - --string-tags-tag-text: inherit; - --string-tags-add-background: inherit; - --string-tags-add-text: var(--accent-3); - - --pill-border: var(--accent-2); - --pill-background: var(--accent-2); - --pill-divider: var(--accent-3); - --pill-input-text: white; - --pill-input-background: var(--accent-2); - --pill-input-disabled-text: white; - --pill-input-disabled-background: black; - - /* Custom HUD Components */ - --DelveDice-background: var(--accent-1); - --DelveDice-text: white; } diff --git a/templates/css/themes/light.css b/templates/css/themes/light.css new file mode 100644 index 0000000..ecb01c7 --- /dev/null +++ b/templates/css/themes/light.css @@ -0,0 +1,14 @@ +.theme-rc-light, +.theme-light { + --header-text: white; + --header-background: black; + + --section-header-text: white; + --section-header-background: black; + + --alt-row-text: black; + --alt-row-background: rgba(0,0,0, 0.3); + + --base-text: black; + --base-background: white; +} \ No newline at end of file