Compare commits

..

222 commits
v0.0.2 ... main

Author SHA1 Message Date
Oliver-Akins
cf13b986d4 Change how embedded ActiveEffects are created 2024-04-27 00:37:49 -06:00
Oliver-Akins
f8364888f2 Fix issues with the localizer's replacement to be more reliable 2024-04-27 00:37:30 -06:00
Oliver-Akins
e2579e12f8 Ignore all ref files in the root rather than just the foundry.js file 2024-04-23 23:19:59 -06:00
Oliver-Akins
2c2c4cc83f Make the AE deletion context menu option actually work 2024-04-23 23:19:23 -06:00
Oliver-Akins
dbeb511bdc Implement the ability to create AE's (closes #177) 2024-04-23 23:18:33 -06:00
Oliver-Akins
ec6378092f Snapshot pre-AE data on actors (closes #178) 2024-04-23 19:47:14 -06:00
Oliver-Akins
d479ef7559 Add basic displaying for ActiveEffects and dropdown support 2024-04-20 23:14:16 -06:00
Oliver-Akins
c466e0e539 Some ActiveEffect shenanigans with training levels 2024-04-20 23:12:38 -06:00
Oliver-Akins
cfaed0d230 Add a generic ActiveEffect class + proxy 2024-04-20 22:08:23 -06:00
Oliver-Akins
8aff8b0fda Remove icon preloading from the systems in favour of the async web component 2024-04-20 21:38:42 -06:00
Oliver-Akins
6b80f3530d Localize the photo dropdown options 2024-04-20 21:29:27 -06:00
Oliver-Akins
002438398b Implement the image context menu functionality (closes #148) 2024-04-20 16:52:37 -06:00
Oliver-Akins
af4f0f60a4 Add layout to the effects tab (closes #145) 2024-04-20 15:40:40 -06:00
Oliver-Akins
6198146c6c Make it so that Materials can only be in unknown location or your inventory 2024-04-19 19:06:15 -06:00
Oliver-Akins
484c7a375c Fix deprecation warnings for v12 2024-04-18 17:37:18 -06:00
Oliver-Akins
2df7d2243f Get the combat relevance toggle working (closes #155) 2024-04-17 22:41:04 -06:00
Oliver-Akins
10449acf37 Makes the calculated capacity viewable on the sheet (closes #158) 2024-04-17 22:36:04 -06:00
Oliver-Akins
c6a7f86926 Implement the Quantity affecting Capacity toggle (closes #157) 2024-04-17 22:34:08 -06:00
Oliver-Akins
48ceade1d1 Implement the toggle for capacity usage. (closes #156) 2024-04-17 22:31:45 -06:00
Oliver-Akins
6d41a33b0c Remove DialogManager from the globalThis 2024-04-15 23:56:50 -06:00
Oliver-Akins
c3bb67ad7c Get the calculated capacity "tooltip" implemented (closes #147 and closes #125) 2024-04-15 23:51:24 -06:00
Oliver-Akins
2737c46ffe Optimization & reorganization of icon files 2024-04-13 17:39:20 -06:00
Oliver-Akins
7e5fc036aa Remove duplicate event listener that's causing an error when editing an item (closes #164) 2024-04-13 17:24:08 -06:00
Oliver-Akins
aa41635f88 Update the inventory icons to be using the dd-icon component 2024-04-13 17:17:15 -06:00
Oliver-Akins
050fecd4f6 Update the material item to use the incrementer component 2024-04-13 17:10:42 -06:00
Oliver-Akins
44eaec2d38 Only listen to custom components that have the name attribute for form submission 2024-04-13 17:09:57 -06:00
Oliver-Akins
8c83d304b7 Remove the really annoying blur on the incrementer component 2024-04-13 17:08:52 -06:00
118dcfb71c
Merge pull request #175 from Oliver-Akins/feature/incrementer-component
Custom Web Components
2024-04-13 14:45:43 -04:00
Oliver-Akins
1598081e3b Add the icon element to the html-data spec 2024-04-13 12:40:09 -06:00
Oliver-Akins
a8c94ee16f Add common SCSS for all custom components 2024-04-13 12:36:32 -06:00
Oliver-Akins
ca0d3eb970 Add a couple incrementer elements as an example for using them 2024-04-13 12:19:32 -06:00
Oliver-Akins
f2c169c077 Make a mixin for loading a stylesheet for components, including HMR auto-update support (only in devMode) 2024-04-13 12:18:36 -06:00
Oliver-Akins
fde3881653 Add Hot Module Replacement for SVG icons using the custom component 2024-04-12 23:23:42 -06:00
Oliver-Akins
f15f3a4456 Get the icon component coded and being used in the incrementer component 2024-04-11 22:32:04 -06:00
Oliver-Akins
3ace1df5a2 Begin work on an icon component 2024-04-10 21:38:44 -06:00
Oliver-Akins
92652262f3 A spot of cleanup 2024-04-10 21:38:30 -06:00
Oliver-Akins
c5c5a71587 Finish the custom incrementer component 2024-04-10 21:27:10 -06:00
Oliver-Akins
878d278303 Remove debug log 2024-04-10 20:52:02 -06:00
Oliver-Akins
1d148d39db Add missing newline 2024-04-07 23:54:44 -06:00
Oliver-Akins
4efa89915a Make progress on the input being focusable from an external label 2024-04-07 23:53:34 -06:00
Oliver-Akins
1c372415f4 Move the CSS into a path-versioned location 2024-04-07 23:08:41 -06:00
Oliver-Akins
1558468526 Add HTML data for the custom incrementer element 2024-04-07 23:07:52 -06:00
Oliver-Akins
e0e4a7b68a Version bump 2024-04-06 15:56:41 -06:00
Oliver-Akins
a0f17fc4f5 Fix item list gaps (closes #163) 2024-04-06 12:03:47 -06:00
Oliver-Akins
14827195fe Version bump 2024-04-06 12:00:51 -06:00
Oliver-Akins
f4d7ea59f3 For now, register all of the devMode stuff in the release 2024-04-06 12:00:36 -06:00
Oliver-Akins
0ac7f07081 Fix a bug with the Sync actor 2024-04-06 12:00:06 -06:00
Oliver-Akins
a1e9c565af Add datasheet for sync sheets 2024-04-06 11:59:27 -06:00
Oliver-Akins
d8b676535f Add incrementer button support for item sheets 2024-04-04 23:14:46 -06:00
Oliver-Akins
96b24d6445 Fix the v3 element CSS from making the inventory nav always visible 2024-04-04 23:14:09 -06:00
Oliver-Akins
81a3e822a8 Get dice rolls working in the new sheet for stats + skills 2024-04-04 23:08:30 -06:00
Oliver-Akins
24d31aad30 Make the read-only state of untyped items usable (closes #162 and #159) 2024-04-04 23:02:43 -06:00
Oliver-Akins
e0a3b4985b Begin making the proper CSS for the component 2024-04-04 22:48:19 -06:00
Oliver-Akins
566faf61d2 Remove stray console logs 2024-04-04 20:02:19 -06:00
Oliver-Akins
9f6a8e5e73 Get the incrementer being able to be submitted, causing submits, and styling without flickering 2024-04-04 19:59:42 -06:00
Oliver-Akins
d5429b7b34 Begin work on a custom element for incrementer 2024-04-03 23:00:57 -06:00
Oliver-Akins
1c2ced321b Add the quantity input to the item details tab (closes #154) 2024-04-01 21:08:59 -06:00
Oliver-Akins
82452f4f7c Fix a bug with the usage cost not being displayed on embedded untyped items 2024-04-01 21:01:31 -06:00
Oliver-Akins
dd5a980f4e Add the locations selector (closes #153) 2024-03-31 15:35:46 -06:00
Oliver-Akins
ad2da03f1e Add edit/viewability to the item rarity (closes #152) 2024-03-31 15:19:19 -06:00
Oliver-Akins
de672642d2 Add edit/view state to the costs of the modal (closes #151) 2024-03-31 13:42:42 -06:00
Oliver-Akins
97ac56dadc Implement the description editing (closes #150) 2024-03-31 11:44:32 -06:00
Oliver-Akins
fc065a5234 Move the context menu above the readonly shortcut to make it possible to view the image without needing edit mode 2024-03-31 00:22:14 -06:00
Oliver-Akins
5a0484190e Add the ability to edit the item names (closes #149) 2024-03-31 00:20:49 -06:00
Oliver-Akins
3a5a3ecc38 Add a context menu to the photo slot (closes #146) 2024-03-30 22:52:45 -06:00
Oliver-Akins
e54857023b Add the layout for the settings tab (closes #144) 2024-03-30 22:41:34 -06:00
Oliver-Akins
9a99f6fc35 Replace the section element for a div 2024-03-30 22:25:31 -06:00
Oliver-Akins
23fc2cb474 Add the layout for the details tab (closes #143) 2024-03-30 22:25:13 -06:00
Oliver-Akins
194eba779d Get the layout for the general tab implemented (closes #142) 2024-03-30 22:16:03 -06:00
Oliver-Akins
df316c68f3 Begin work on the updated item sheet and get the tabs initialized (Closes #141) 2024-03-30 22:02:39 -06:00
Oliver-Akins
be31e98dea Tweak the way that the logic for usedCapacity is working to make it correct and bit easier to read 2024-03-30 13:00:05 -06:00
Oliver-Akins
0f28e23b5c Add a datasheet for untyped items and foils 2024-03-30 12:59:16 -06:00
Oliver-Akins
3d8d041915 Add an item property for if the item is combat relevant 2024-03-30 00:43:47 -06:00
Oliver-Akins
19666a4e05 Clean up the Player datamodel, invalidating almost everything lol 2024-03-30 00:43:23 -06:00
Oliver-Akins
eadaa53c75 Begin working on a scoped CSS solution that uses a common design language across all sheets, and *just* does sheet-specific layout tasks 2024-03-26 22:36:40 -06:00
Oliver-Akins
5c5a1a8b56 Remove translation literals for now 2024-03-26 18:42:38 -06:00
Oliver-Akins
f4014e9c35 Add type augments for classes so intellisense doesn't keep converting system to migrateSystemData 2024-03-26 18:37:13 -06:00
Oliver-Akins
4c11a21d09 Gitignore all dot-prefixed folders at the root except .vscode and .github 2024-03-25 23:34:48 -06:00
Oliver-Akins
71c091e04a Fix an issue with the capacity calculation not working on items that don't have a quantity (surprisingly more than expected) 2024-03-25 22:55:58 -06:00
c03cd1dcd7
Merge pull request #136 from Oliver-Akins/feature/item-context-menus
Embedded Material context menu
2024-03-25 22:54:38 -06:00
Oliver-Akins
fe4abd073f Add a context menu for the material so that it can be edited and deleted (closes #133) 2024-03-25 22:52:33 -06:00
Oliver-Akins
c7bafee6b6 Misc template cleanup / consistency 2024-03-25 21:34:23 -06:00
Oliver-Akins
36976e5123 Add the pet details (closes #135) 2024-03-25 21:33:14 -06:00
Oliver-Akins
6504e33fad Remove prototype code that shouldn't be committed on main yet 2024-03-25 21:24:32 -06:00
Oliver-Akins
97af3801c4 Make it so we don't need to re-render the sheet on collapse toggle 2024-03-25 19:08:32 -06:00
Oliver-Akins
34eae97b47 Enable the foils filter by default 2024-03-24 21:49:43 -06:00
Oliver-Akins
337370bbfe Add the Weapon item details (closes #132) 2024-03-24 21:47:59 -06:00
Oliver-Akins
60797ab1e2 Don't cause rerender jumps for scrollable elements (closes #131) 2024-03-24 21:46:11 -06:00
Oliver-Akins
ec07fcfd39 Add a couple of utility macros for making development easier when invalidating documents 2024-03-24 17:23:46 -06:00
Oliver-Akins
acbcb6c9b2 Genericizing some of the styling and adding the Aspect item details (closes #128) 2024-03-24 16:54:50 -06:00
Oliver-Akins
649381cfdd Make the friendly duration be a getter on the Aspect class 2024-03-24 16:53:12 -06:00
Oliver-Akins
b19d248bc8 Remove the toFriendlyDuration helper 2024-03-24 16:52:30 -06:00
Oliver-Akins
022a63f12f Tweak Checkbox styles for the actor sheet 2024-03-24 16:50:33 -06:00
Oliver-Akins
8c9d8125f2 Register the datamodel for foils 2024-03-23 13:01:25 -06:00
Oliver-Akins
8ef9bd2550 Make it so that I can specifically code some aliases for handlebar partials 2024-03-23 13:01:07 -06:00
Oliver-Akins
07517658e7 Remove transportation as a location value 2024-03-23 13:00:26 -06:00
Oliver-Akins
1ba6cd0617 Remove properties from the data model that aspects don't need 2024-03-23 13:00:09 -06:00
Oliver-Akins
96f5b17785 Implement a button to create items of a specific subtype in the player inventory (closes #120) 2024-03-22 23:35:04 -06:00
Oliver-Akins
b3e699bc32 Harden the preCreate quantity increase to use source IDs in finding the item 2024-03-22 21:47:29 -06:00
Oliver-Akins
55a64afe02 Add a helper function for visible empty states 2024-03-22 20:23:51 -06:00
Oliver-Akins
18cdc2addc Get the item embedding working in a cleaner way where most of the item embedding logic is handled in the item's class instead of the actor's class 2024-03-22 20:23:28 -06:00
Oliver-Akins
0605542d62 Remove console log 2024-03-21 21:24:37 -06:00
Oliver-Akins
bad95f8c18 Begin making the pre-embed quantity change logic based on source IDs and not name 2024-03-21 21:24:26 -06:00
Oliver-Akins
6a355e63c0 Get most of the Untyped item implemented and functioning 2024-03-21 21:18:51 -06:00
Oliver-Akins
a383225b8c Add a couple of notes for a method I want to tweak later 2024-03-21 00:26:36 -06:00
Oliver-Akins
d64ed37953 Tweak the scrollbar stuff and make the scrollable gutter stable 2024-03-21 00:21:17 -06:00
Oliver-Akins
68b53601d6 Allow customizing the scrollbar on a per-sheet-per-theme basis as desired 2024-03-21 00:02:23 -06:00
Oliver-Akins
3b4e2405c1 Get the general layout of the untyped item details ready 2024-03-20 23:42:47 -06:00
Oliver-Akins
df38113533 Simplify logic that I did weirdly for some reason 2024-03-20 21:20:51 -06:00
Oliver-Akins
6db5818184 Add caret-down icon 2024-03-20 19:08:00 -06:00
Oliver-Akins
25a1e7e574 Remove stub 2024-03-20 19:07:44 -06:00
Oliver-Akins
80995da0aa Begin work on the Untyped item info 2024-03-20 19:07:25 -06:00
Oliver-Akins
aa5c6d5aba Improve how capacity consumption calculations are performed 2024-03-20 17:56:41 -06:00
Oliver-Akins
cf109a6ed1 Fix my erroneous reduce 2024-03-19 23:37:29 -06:00
Oliver-Akins
83d0bad21f Get the material items finished 2024-03-19 23:30:58 -06:00
Oliver-Akins
310ac07c88 Add data model for materials 2024-03-19 23:30:00 -06:00
Oliver-Akins
d69790ce89 Have Foundry reload automatically when it detects JS changes 2024-03-19 23:29:31 -06:00
Oliver-Akins
0304af3695 Move sheet logic into the sheet class... 2024-03-19 23:29:14 -06:00
Oliver-Akins
59b64f57db Fix the instanceof operators on the proxy to include the default class 2024-03-19 19:35:14 -06:00
Oliver-Akins
23ec5fe0d3 Add a supplies incrementer in the left side-bar 2024-03-18 23:29:23 -06:00
Oliver-Akins
30ed81cafa Prevent data from being undefined within actors and sheets because of my attempt at getting TS to play nicely 2024-03-18 23:28:55 -06:00
Oliver-Akins
33ccb01a6f Change import order 2024-03-18 23:20:54 -06:00
Oliver-Akins
62554d1622 Remove console logs 2024-03-18 23:20:27 -06:00
Oliver-Akins
0c1149a21c Fix broken imports 2024-03-18 23:20:17 -06:00
Oliver-Akins
cd98e66484 Make the system use Proxy and proper subclassing instead of the weird middle-ground polymorphism (closes #86) 2024-03-18 23:16:17 -06:00
Oliver-Akins
745824f6cc Add TYPE translation literals 2024-03-17 21:27:46 -06:00
Oliver-Akins
7549cd2b05 Change VSC settings 2024-03-17 21:27:16 -06:00
Oliver-Akins
82f1499c3d Add stub partial for the incrementer component 2024-03-17 21:27:01 -06:00
Oliver-Akins
992ae094b2 Remove the transportation partial's inclusion from the sheet 2024-03-17 21:14:20 -06:00
Oliver-Akins
6d14d70f3e Lay the foundation for the per-item templating in the inventory 2024-03-17 21:10:34 -06:00
Oliver-Akins
5e2fb95c73 Update item data models 2024-03-17 19:47:06 -06:00
Oliver-Akins
27c30b7eef Add the effects handlebars templates 2024-03-17 19:46:13 -06:00
Oliver-Akins
d131e2faaa Remove Transportation as an item subtype 2024-03-17 19:45:47 -06:00
Oliver-Akins
47183da268 Add a tab to list all effects 2024-03-17 17:10:04 -06:00
Oliver-Akins
c716f0dbbd Add the code I forgot to commit for the functional filters 2024-03-17 17:08:17 -06:00
Oliver-Akins
3c412dde32 Finish getting the item filters toggling and scrolling the single panel 2024-03-17 17:03:01 -06:00
Oliver-Akins
5fe854a0f3 Do some logic tweaks for the item filter functionality 2024-03-17 13:40:31 -06:00
Oliver-Akins
aab71df1fc Add the capacity display (closes #96) 2024-03-17 12:54:15 -06:00
Oliver-Akins
b6ca477be7 Add transportation item section (closes #105) 2024-03-17 11:59:18 -06:00
Oliver-Akins
8a51a75233 Adds the structures item section (closes #104) 2024-03-17 11:58:27 -06:00
Oliver-Akins
4e3a588c57 Add armour item section (closes #101) 2024-03-17 11:56:54 -06:00
Oliver-Akins
470f5b6225 Add weapons item section (closes #100) 2024-03-17 11:54:03 -06:00
Oliver-Akins
46e7d674d3 Add equipment item section (closes #103) 2024-03-17 11:52:04 -06:00
Oliver-Akins
afbb9bbe02 Add the aspects section (closes #102) 2024-03-17 11:44:25 -06:00
Oliver-Akins
79b0431ead Add untyped item section (closes #106) 2024-03-17 11:35:50 -06:00
Oliver-Akins
364ebd06f2 Add materials section placeholder (closes #99) 2024-03-17 11:32:57 -06:00
Oliver-Akins
54d047d240 Add references file to gitignore 2024-03-17 11:22:25 -06:00
Oliver-Akins
d100af3198 Rename PlayerSheetV2 containing file 2024-03-17 11:22:08 -06:00
Oliver-Akins
3981e95ff0 Add item list placeholder. (Closes #98) 2024-03-17 11:21:41 -06:00
Oliver-Akins
609b5820ba Add the filter checkboxes and infra for toggling them (closes #110) 2024-03-08 22:27:04 -07:00
Oliver-Akins
c525c1390b Add display to the capacity panel (closes #95) 2024-03-08 21:19:00 -07:00
Oliver-Akins
e6e392d7e5 Add the bytes panel to the page. (closes #108) 2024-03-08 21:14:30 -07:00
Oliver-Akins
42bd07707d Ignore zips 2024-03-08 20:40:39 -07:00
Oliver-Akins
daaa459012 Implement the general layout for inventory (closes #94) 2024-03-04 19:41:59 -07:00
Oliver-Akins
cd6554289b Make the nav buttons look like designs (closes #107) 2024-03-04 19:38:58 -07:00
Oliver-Akins
5f09f92790 Implement the Inventory tab's sub-navigation (closes #97) 2024-03-02 22:40:32 -07:00
Oliver-Akins
2065596686 Fix the localization function and provide a special placeholder for when the user doesn't have a die assigned to their stat 2024-03-02 00:28:23 -07:00
Oliver-Akins
c1ee1a9ef8 Get 95% of the way through the stats tab 2024-03-01 23:28:18 -07:00
Oliver-Akins
7516e7b42b Implement the custom options helper (closes #92) 2024-03-01 18:34:16 -07:00
Oliver-Akins
0e8d1615a7 Begin implementation of the Stats / Skills tab 2024-02-29 22:35:28 -07:00
Oliver-Akins
753d72b4e0 Continue working on v2 of the PC sheet (w/ Material design now) 2024-02-27 22:49:39 -07:00
Oliver-Akins
6d2d02b077 Begin working on the non-MVP character sheet 2024-02-25 23:25:18 -07:00
Oliver-Akins
d74416c620 Rename existing PC sheet to make it more obvious it's the MVP 2024-02-25 19:53:41 -07:00
Oliver-Akins
b123bea62c Begin writing the specification for the new PC sheet 2024-02-25 00:56:46 -07:00
Oliver-Akins
fb4026dcce Disable VSC branch protection and hide some files that I don't care to see in the file browser 2024-02-24 13:41:17 -07:00
Oliver-Akins
19588bb137 Begin work on the localization cycle prevention and add newline to existing scripts 2024-02-24 13:40:25 -07:00
Oliver-Akins
bbd96d3b45 Ignore lockfiles 2024-02-24 12:16:13 -07:00
Oliver-Akins
b4509555f3 On to 0.0.7 2024-02-24 12:15:48 -07:00
Oliver-Akins
1ca9958c52 Version bump 2024-02-22 22:51:59 -07:00
Oliver-Akins
c1fa5b3d9b Implement utility function that recursively localizes based on the config data (implements #54) 2024-02-22 22:49:02 -07:00
Oliver-Akins
34c7dbed87 Pull the generic data for the aspect sheet (closes #81) 2024-02-22 19:34:16 -07:00
Oliver-Akins
bb542b8545 Add adventures compendium 2024-02-15 22:12:33 -07:00
Oliver-Akins
a0f8566104 Add utility script for extracting the compendia to JSON 2024-02-15 22:12:03 -07:00
Oliver-Akins
696717aa1c Update the compendia packs 2024-02-15 22:11:28 -07:00
Oliver-Akins
8971f25b9d Prevent erroring when the compendium doesn't have anything 2024-02-13 21:14:54 -07:00
Oliver-Akins
411ddca927 Add a compendium build step in the Github action 2024-02-13 21:08:13 -07:00
Oliver-Akins
1a102074d5 Tell git to ignore the compiled files from Foundry 2024-02-13 20:07:51 -07:00
Oliver-Akins
29a1e0eacf Prevent partial-updates from being overwritten when adding/deleting a dice (closes #87) 2024-02-13 20:07:34 -07:00
Oliver-Akins
2a7d485ab4 Fix indentation 2024-02-13 20:06:44 -07:00
Oliver-Akins
a9e926c6b4 Purge all of the compiled files so that I can just have them be built with my Github action during release prep instead 2024-02-13 20:06:36 -07:00
Oliver-Akins
1177ed36aa Add some compendium data 2024-02-11 14:25:58 -07:00
Oliver-Akins
931b6a96d0 Add EOF newlines to all files that don't have it already for consistency 2024-02-10 22:55:45 -07:00
Oliver-Akins
0770f32ef5 Use the Foundry util function instead of the custom one 2024-02-10 13:26:43 -07:00
Oliver-Akins
30fee77c8e Cleanup log statement 2024-02-10 13:22:20 -07:00
Oliver-Akins
cad3cdd5f1 Switch quotes 2024-02-10 01:03:59 -07:00
Oliver-Akins
914b6e5862 Implement initiative rolling within Foundry 2024-02-10 01:03:49 -07:00
Oliver-Akins
1002b1387c Add rest dice tracking for the Sync actors 2024-02-08 23:25:55 -07:00
Oliver-Akins
4544516c5c Implement the buttons spinbuttons for the inventory area 2024-02-07 19:39:24 -07:00
Oliver-Akins
1c737b3dc4 Fighting TS isn't worth the effort 2024-02-07 18:26:08 -07:00
Oliver-Akins
990a7c1bed Augment the global namespace 2024-02-07 17:45:23 -07:00
Oliver-Akins
10c118d846 Remove maximum value from supplies and materials 2024-02-07 17:45:06 -07:00
Oliver-Akins
8786e4781d Finish augmenting the Game class 2024-02-06 22:22:33 -07:00
Oliver-Akins
bfc8a343b5 Add missing newline 2024-02-06 22:07:49 -07:00
Oliver-Akins
11f01aed8d Add style for the horizontal rules to make it actually work 2024-02-06 22:07:33 -07:00
Oliver-Akins
8ea1c82de8 Add proper support for the TS language server to be able to have proper type checking because of the way Foundry sets some properties 2024-02-06 21:57:13 -07:00
Oliver-Akins
7067615da7 Some miscellanious cleanup 2024-02-06 20:42:56 -07:00
Oliver-Akins
2f8ec1b79c Finish the Inventory item improvements 2024-02-06 19:29:05 -07:00
Oliver-Akins
83039c6144 Add the ability to create custom items 2024-02-04 22:05:44 -07:00
Oliver-Akins
23dd021df6 Move context preparation common to all items into the GenericItemSheet 2024-02-04 21:13:40 -07:00
Oliver-Akins
acd4d35da0 Move some of the new design language CSS into a common location 2024-02-04 20:34:43 -07:00
Oliver-Akins
e284529a45 Update location of sheets to keep them more organized 2024-02-04 20:04:26 -07:00
Oliver-Akins
6fbb480f83 Default the weapon names to an empty string 2024-02-04 19:47:56 -07:00
Oliver-Akins
68362def85 I hate HTML... it's so icky 2024-02-04 19:45:09 -07:00
Oliver-Akins
60cfd0f1bb On to 0.0.5 2024-02-04 19:01:49 -07:00
Oliver-Akins
f5a6c30248 Prevent the data migration code from preventing any editing 2024-02-04 19:01:39 -07:00
Oliver-Akins
11b721a4cb Create data migration test for Mobs 2024-02-03 17:52:10 -07:00
Oliver-Akins
1bc141d91a Remove data migration stuff that doesn't need to exist 2024-02-03 17:50:01 -07:00
Oliver-Akins
46555ec807 File cleanup 2024-02-03 17:49:43 -07:00
Oliver-Akins
52aaa41d86 Implement the dice list form and tweak some design variables 2024-02-03 13:57:31 -07:00
Oliver-Akins
15462c98fb Find roll buttons via data-roll-formula and not the roll class. 2024-02-03 13:33:03 -07:00
Oliver-Akins
0deda3235a Begin work on the custom editor for dice 2024-02-03 00:12:08 -07:00
Oliver-Akins
36e3a551b8 Add description to the mob data model 2024-02-02 19:12:04 -07:00
Oliver-Akins
91a98d3d2a Add bytes to the Mob data model 2024-02-02 19:11:25 -07:00
Oliver-Akins
aee607e1bc Add immune and weak to the Mob data model 2024-02-02 19:10:11 -07:00
Oliver-Akins
e862165689 Tweak the design so that Drops and a Description can be fit into the sheet 2024-02-02 19:07:07 -07:00
Oliver-Akins
dabbc4e850 Cleanup files 2024-02-01 22:08:25 -07:00
Oliver-Akins
e858be6fa2 Add the .styles folder to the gitignore 2024-02-01 22:07:08 -07:00
Oliver-Akins
47a3461680 Purge the compiled CSS from the repo 2024-02-01 22:06:44 -07:00
Oliver-Akins
3bb36cde58 Improve design and layout of the mob sheet 2024-02-01 22:06:14 -07:00
Oliver-Akins
cdaaaef34d On to v0.0.4 2024-01-31 18:45:33 -07:00
Oliver-Akins
a657b2e3e8 Load icons during initial setup and allow hot-reloading icons 2024-01-31 18:34:24 -07:00
Oliver-Akins
b9ed3289dc Begin work on 0.0.3 2024-01-31 18:17:41 -07:00
247 changed files with 8759 additions and 2078 deletions

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
packs/** binary

View file

@ -35,6 +35,7 @@ jobs:
# Compile the stuff that needs to be compiled
- run: npm run build
- run: node scripts/buildCompendia.mjs
- name: Move system.json to a temp file
id: manifest-move

14
.gitignore vendored
View file

@ -2,3 +2,17 @@ node_modules/
*.tmp
*.bak.*
references.txt
references/
/.*/
!/.vscode/
!/.github/
/*.ref.*
*.lock
*.zip
# 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

View file

@ -1,69 +0,0 @@
@import url("https://fonts.googleapis.com/css2?family=Pixelify+Sans&display=swap");
.dotdungeon > .window-content ::-webkit-scrollbar {
width: 10px;
}
.dotdungeon > .window-content ::-webkit-scrollbar-thumb {
border-radius: 5px;
}
.dotdungeon > .window-content h2, .dotdungeon > .window-content h3, .dotdungeon > .window-content h4, .dotdungeon > .window-content h5, .dotdungeon > .window-content h6 {
all: initial;
display: block;
box-sizing: border-box;
font-family: "Pixelify Sans", sans-serif;
margin: 0;
}
.dotdungeon > .window-content label {
cursor: pointer;
}
.dotdungeon > .window-content button, .dotdungeon > .window-content button:hover {
all: initial;
display: block;
box-sizing: border-box;
font-family: inherit;
cursor: pointer;
}
.dotdungeon > .window-content button:disabled, .dotdungeon > .window-content button:hover:disabled {
cursor: default;
}
.dotdungeon > .window-content input[type=text],
.dotdungeon > .window-content input[type=number],
.dotdungeon > .window-content textarea {
padding: 5px 7px;
border-width: 2px;
border-radius: 4px;
border-style: solid;
border-color: rgba(0, 0, 0, 0.4);
background-color: rgba(0, 0, 0, 0.1);
font-family: sans-serif;
}
.dotdungeon > .window-content input[type=text]:focus, .dotdungeon > .window-content input[type=text]:active,
.dotdungeon > .window-content input[type=number]:focus,
.dotdungeon > .window-content input[type=number]:active,
.dotdungeon > .window-content textarea:focus,
.dotdungeon > .window-content textarea:active {
border-color: rgb(0, 0, 0);
}
.dotdungeon > .window-content textarea {
resize: vertical;
}
.dotdungeon > .window-content select, .dotdungeon > .window-content select:hover {
cursor: pointer;
}
.dotdungeon > .window-content select :disabled, .dotdungeon > .window-content select:hover :disabled {
cursor: default;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon {
container-type: size;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content {
padding: 0;
background: #f2f2f2;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content .debug-data {
opacity: 60%;
font-family: sans-serif;
word-break: break-all;
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../styles/generic.scss%22,%22../styles/mixins/_foundry.scss%22,%22../styles/_vars.scss%22,%22../styles/mixins/_partials.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAIQ;AAKP;EACC;;AAED;EACC;;AAGD;ECfA;EACA;EACA;EDeC,aEhBW;EFiBX;;AAGD;EACC;;AAGD;ECzBA;EACA;EACA;EDyBC;EACA;;AAEA;EACC;;AAIF;AAAA;AAAA;EAGC;EGpCD;EACA;EACA;EACA;EACA;EACA,aDLW;;ACOX;AAAA;AAAA;AAAA;AAAA;EAEC;;AH+BD;EACC;;AAGD;EACC;;AAEA;EACC;;;AAMH;EACC;;AAEA;EACC;EACA,YEzDW;;AF2DX;EACC;EACA,aE/DS;EFgET%22,%22file%22:%22generic.css%22%7D */

View file

@ -1,52 +0,0 @@
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button {
border-radius: 4px;
box-sizing: border-box;
border-style: solid;
border-color: transparent;
border-width: 2px;
border-radius: 4px;
transition: 400ms;
padding: 4px 8px;
display: inline-flex;
justify-content: center;
align-items: center;
gap: 4px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.confirm {
background: #048A81;
color: white;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.confirm:hover, .dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.confirm:focus-visible {
background: transparent;
color: #048A81;
border-color: #048A81;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.neutral {
background: #007ACC;
color: white;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.neutral:hover, .dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.neutral:focus-visible {
background: transparent;
color: #007ACC;
border-color: #007ACC;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.danger {
background: #960200;
color: white;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.danger:hover, .dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.danger:focus-visible {
background: transparent;
color: #960200;
border-color: #960200;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.reduced-padding {
padding: 2px 4px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.equal-padding {
padding: 4px 4px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.equal-padding.reduced-padding {
padding: 2px 2px;
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../../styles/global/buttons.scss%22,%22../../styles/_vars.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAGC;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC,YCXc;EDYd,OCXe;;ADYf;EACC;EACA,OCfa;EDgBb,cChBa;;ADoBf;EACC,YClBc;EDmBd,OClBe;;ADmBf;EACC;EACA,OCtBa;EDuBb,cCvBa;;AD2Bf;EACC,YCzBa;ED0Bb,OCzBc;;AD0Bd;EACC;EACA,OC7BY;ED8BZ,cC9BY;;ADkCd;EACC;;AAID;EACC;;AACA;EACC%22,%22file%22:%22buttons.css%22%7D */

View file

@ -1,35 +0,0 @@
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon {
display: inline-flex;
justify-content: center;
align-items: center;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--12 {
height: 12px;
width: 12px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--14 {
height: 14px;
width: 14px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--16 {
height: 16px;
width: 16px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--18 {
height: 18px;
width: 18px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--20 {
height: 20px;
width: 20px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--22 {
height: 22px;
width: 22px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--24 {
height: 24px;
width: 24px;
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../../styles/global/icons.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAGC;EACC;EACA;EACA;;AAIC;EACC;EACA;;AAFD;EACC;EACA;;AAFD;EACC;EACA;;AAFD;EACC;EACA;;AAFD;EACC;EACA;;AAFD;EACC;EACA;;AAFD;EACC;EACA%22,%22file%22:%22icons.css%22%7D */

View file

@ -1,530 +0,0 @@
@import url("https://fonts.googleapis.com/css2?family=Pixelify+Sans&display=swap");
.dotdungeon > .window-content ::-webkit-scrollbar {
width: 10px;
}
.dotdungeon > .window-content ::-webkit-scrollbar-thumb {
border-radius: 5px;
}
.dotdungeon > .window-content h2, .dotdungeon > .window-content h3, .dotdungeon > .window-content h4, .dotdungeon > .window-content h5, .dotdungeon > .window-content h6 {
all: initial;
display: block;
box-sizing: border-box;
font-family: "Pixelify Sans", sans-serif;
margin: 0;
}
.dotdungeon > .window-content label {
cursor: pointer;
}
.dotdungeon > .window-content button, .dotdungeon > .window-content button:hover {
all: initial;
display: block;
box-sizing: border-box;
font-family: inherit;
cursor: pointer;
}
.dotdungeon > .window-content button:disabled, .dotdungeon > .window-content button:hover:disabled {
cursor: default;
}
.dotdungeon > .window-content input[type=text],
.dotdungeon > .window-content input[type=number],
.dotdungeon > .window-content textarea {
padding: 5px 7px;
border-width: 2px;
border-radius: 4px;
border-style: solid;
border-color: rgba(0, 0, 0, 0.4);
background-color: rgba(0, 0, 0, 0.1);
font-family: sans-serif;
}
.dotdungeon > .window-content input[type=text]:focus, .dotdungeon > .window-content input[type=text]:active,
.dotdungeon > .window-content input[type=number]:focus,
.dotdungeon > .window-content input[type=number]:active,
.dotdungeon > .window-content textarea:focus,
.dotdungeon > .window-content textarea:active {
border-color: rgb(0, 0, 0);
}
.dotdungeon > .window-content textarea {
resize: vertical;
}
.dotdungeon > .window-content select, .dotdungeon > .window-content select:hover {
cursor: pointer;
}
.dotdungeon > .window-content select :disabled, .dotdungeon > .window-content select:hover :disabled {
cursor: default;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon {
container-type: size;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content {
padding: 0;
background: #f2f2f2;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content .debug-data {
opacity: 60%;
font-family: sans-serif;
word-break: break-all;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon {
display: inline-flex;
justify-content: center;
align-items: center;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--12 {
height: 12px;
width: 12px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--14 {
height: 14px;
width: 14px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--16 {
height: 16px;
width: 16px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--18 {
height: 18px;
width: 18px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--20 {
height: 20px;
width: 20px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--22 {
height: 22px;
width: 22px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon .icon--24 {
height: 24px;
width: 24px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button {
border-radius: 4px;
box-sizing: border-box;
border-style: solid;
border-color: transparent;
border-width: 2px;
border-radius: 4px;
transition: 400ms;
padding: 4px 8px;
display: inline-flex;
justify-content: center;
align-items: center;
gap: 4px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.confirm {
background: #048A81;
color: white;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.confirm:hover, .dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.confirm:focus-visible {
background: transparent;
color: #048A81;
border-color: #048A81;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.neutral {
background: #007ACC;
color: white;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.neutral:hover, .dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.neutral:focus-visible {
background: transparent;
color: #007ACC;
border-color: #007ACC;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.danger {
background: #960200;
color: white;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.danger:hover, .dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.danger:focus-visible {
background: transparent;
color: #960200;
border-color: #960200;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.reduced-padding {
padding: 2px 4px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.equal-padding {
padding: 4px 4px;
}
.dotdungeon.dotdungeon.dotdungeon.dotdungeon > .window-content button.equal-padding.reduced-padding {
padding: 2px 2px;
}
.dotdungeon .stat {
display: flex;
flex-direction: column;
align-items: center;
}
.dotdungeon .skill {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 100%;
gap: 8px;
}
.dotdungeon .skill-group {
display: flex;
flex-direction: column;
justify-content: center;
gap: 4px;
}
.dotdungeon .skill-group h3 {
margin-top: 8px;
font-size: 1.2em;
width: 100%;
text-align: center;
}
.dotdungeon .panel {
display: grid;
grid-template-rows: min-content 1fr;
border: 2px solid black;
}
.dotdungeon .panel__header {
background: black;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 4px;
padding: 0 4px;
}
.dotdungeon .panel__header h2 {
all: initial;
display: block;
box-sizing: border-box;
color: white;
flex-grow: 1;
font-family: "Pixelify Sans", sans-serif;
font-size: 20px;
}
.dotdungeon .panel__header .icon {
height: 20px;
width: 20px;
aspect-ratio: 1/1;
}
.dotdungeon .panel__content {
padding: 8px;
}
@container (max-width: 400px) {
.dotdungeon .panel__header .icon {
display: none;
visibility: hidden;
}
}
.dotdungeon .actor--pc {
display: grid;
grid-template-areas: "profile stats stats" "profile skills skills" "sync skills skills" "spells weapons aspect" "spells weapons aspect" "backpack roles mounts" "backpack roles mounts" "pets storage storage" "pets storage storage";
grid-template-columns: repeat(3, minmax(0, 1fr));
grid-template-rows: min-content 1fr repeat(7, min-content);
padding: 4px;
gap: 4px;
}
.dotdungeon .actor--pc details {
border-radius: 4px;
background-color: rgba(0, 0, 0, 0.2);
padding: 4px;
margin-bottom: 8px;
}
.dotdungeon .actor--pc details summary {
cursor: pointer;
}
.dotdungeon .actor--pc details[open] .expanded-rotate {
transform: rotate(90deg);
}
.dotdungeon .actor--pc .panel--profile {
grid-area: profile;
}
.dotdungeon .actor--pc .panel--profile .avatar {
width: 100%;
aspect-ratio: 1/1;
}
.dotdungeon .actor--pc .panel--profile label, .dotdungeon .actor--pc .panel--profile input {
width: 100%;
}
.dotdungeon .actor--pc .panel--stats {
grid-area: stats;
}
.dotdungeon .actor--pc .panel--stats .panel__content {
display: flex;
flex-direction: row;
gap: 8px;
justify-content: space-evenly;
padding: 8px;
flex-wrap: wrap;
}
.dotdungeon .actor--pc .panel--skills {
grid-area: skills;
}
.dotdungeon .actor--pc .panel--skills .panel__content {
display: grid;
row-gap: 8px;
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-template-rows: repeat(2, minmax(0, min-content));
}
.dotdungeon .actor--pc .panel--backpack {
grid-area: backpack;
}
.dotdungeon .actor--pc .panel--backpack .row {
display: flex;
flex-direction: row;
align-items: center;
}
.dotdungeon .actor--pc .panel--backpack .col {
display: flex;
flex-direction: column;
}
.dotdungeon .actor--pc .panel--backpack .grow {
flex-grow: 1;
}
.dotdungeon .actor--pc .panel--backpack .panel__content {
display: flex;
flex-direction: column;
gap: 4px;
}
.dotdungeon .actor--pc .panel--backpack .bytes-input,
.dotdungeon .actor--pc .panel--backpack .supplies-count,
.dotdungeon .actor--pc .panel--backpack .materials-count {
width: 25%;
text-align: center;
}
.dotdungeon .actor--pc .panel--backpack textarea {
resize: vertical;
}
.dotdungeon .actor--pc .panel--sync {
grid-area: sync;
}
.dotdungeon .actor--pc .panel--sync .panel__content {
display: flex;
flex-direction: column;
gap: 4px;
}
.dotdungeon .actor--pc .panel--sync .respawns,
.dotdungeon .actor--pc .panel--sync .sync {
display: flex;
flex-direction: row;
align-items: center;
}
.dotdungeon .actor--pc .panel--sync .respawns__header,
.dotdungeon .actor--pc .panel--sync .sync__header {
flex-grow: 1;
}
.dotdungeon .actor--pc .panel--sync .sync__input {
width: 80px;
margin: 3px 5px;
}
.dotdungeon .actor--pc .panel--aspect {
grid-area: aspect;
}
.dotdungeon .actor--pc .panel--aspect .panel__content {
display: grid;
grid-template-rows: min-content min-content;
gap: 4px;
text-align: center;
}
.dotdungeon .actor--pc .panel--aspect .panel__content textarea {
resize: vertical;
}
.dotdungeon .actor--pc .panel--aspect .aspect__used {
display: flex;
align-items: center;
gap: 4px;
}
.dotdungeon .actor--pc .panel--aspect .aspect__used--input {
margin: 0;
}
.dotdungeon .actor--pc .panel--weapons {
grid-area: weapons;
}
.dotdungeon .actor--pc .panel--weapons .weapon {
margin-top: 4px;
display: flex;
flex-direction: column;
gap: 4px;
}
.dotdungeon .actor--pc .panel--weapons .weapon__name {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.dotdungeon .actor--pc .panel--weapons .weapon__name input {
width: 50%;
}
.dotdungeon .actor--pc .panel--weapons .weapon__group {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4px;
}
.dotdungeon .actor--pc .panel--weapons .weapon__ammo-type, .dotdungeon .actor--pc .panel--weapons .weapon__damage-type {
display: flex;
flex-direction: column;
align-items: center;
}
.dotdungeon .actor--pc .panel--weapons .weapon__is-scoped, .dotdungeon .actor--pc .panel--weapons .weapon__is-ranged {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.dotdungeon .actor--pc .panel--roles {
grid-area: roles;
}
.dotdungeon .actor--pc .panel--roles .panel__content {
display: grid;
grid-template-rows: repeat(4, min-content);
height: 100%;
gap: 4px;
}
.dotdungeon .actor--pc .panel--roles .panel__content textarea {
resize: vertical;
}
.dotdungeon .actor--pc .panel--spells {
grid-area: spells;
}
.dotdungeon .actor--pc .panel--spells .spell {
display: flex;
flex-direction: column;
gap: 4px;
}
.dotdungeon .actor--pc .panel--spells .spell .placeholder {
opacity: 75%;
}
.dotdungeon .actor--pc .panel--spells .panel__content {
display: flex;
gap: 4px;
flex-direction: column;
}
.dotdungeon .actor--pc .panel--mounts {
grid-area: mounts;
}
.dotdungeon .actor--pc .panel--pets {
grid-area: pets;
}
.dotdungeon .actor--pc .panel--pets .panel__content {
display: grid;
grid-template-rows: min-content min-content;
gap: 4px;
}
.dotdungeon .actor--pc .panel--pets .panel__content textarea {
resize: vertical;
}
.dotdungeon .actor--pc .panel--storage {
grid-area: storage;
}
.dotdungeon .actor--pc .actions {
display: flex;
flex-direction: row;
justify-content: end;
gap: 4px;
}
.dotdungeon .actor--pc .panel__content .center {
text-align: center;
}
@container (max-width: 620px) {
.dotdungeon .actor--pc {
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-template-rows: repeat(15, min-content);
grid-template-areas: "profile stats" "profile skills" "sync skills" "weapons skills" "weapons skills" "backpack aspect" "backpack aspect" "backpack roles" "backpack roles" "backpack roles" "backpack spells" "pets spells" "pets storage" "mounts storage" "mounts storage";
}
.dotdungeon .actor--pc .panel--stats .panel__content {
flex-wrap: wrap;
}
.dotdungeon .actor--pc .panel--skills .panel__content {
display: flex;
flex-direction: column;
}
}
@container (max-width: 400px) {
.dotdungeon .actor--pc {
grid-template-columns: 1fr;
grid-template-rows: repeat(12, min-content);
grid-template-areas: "profile" "stats" "sync" "skills" "aspect" "roles" "backpack" "weapons" "spells" "mounts" "pets" "storage";
}
.dotdungeon .actor--pc .panel--skills .skill {
flex-direction: column;
}
}
.dotdungeon .actor--mob {
padding: 4px;
}
.dotdungeon .actor--mob textarea {
width: 100%;
resize: vertical;
}
.dotdungeon .actor--basic-sync {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
gap: 4px;
}
.dotdungeon .actor--basic-sync label {
display: flex;
flex-direction: column;
align-items: center;
}
.dotdungeon .actor--basic-sync .sync-input {
width: 30%;
text-align: center;
}
.dotdungeon .actor--basic-sync .name-input {
width: 60%;
text-align: center;
}
.dotdungeon--sync-sheet header .configure-token {
display: none;
visibility: hidden;
}
@container (max-width: 300px) {
.dotdungeon--sync-sheet header .configure-sheet {
display: none;
visibility: hidden;
}
}
.dotdungeon .item--aspect {
padding: 4px;
}
.dotdungeon .item--aspect input[type=text] {
font-size: 1.5em;
height: 1.5em;
width: 100%;
}
.dotdungeon .item--aspect textarea {
width: 100%;
resize: vertical;
}
.dotdungeon .item--spell {
padding: 4px;
}
.dotdungeon .item--spell input[type=text] {
font-size: 1.5em;
height: 1.5em;
width: 100%;
}
.dotdungeon .item--spell textarea {
width: 100%;
resize: vertical;
}
.dotdungeon .item--pet {
padding: 4px;
}
.dotdungeon .item--pet input[type=text] {
font-size: 1.5em;
height: 1.5em;
width: 100%;
}
.dotdungeon .item--pet textarea {
width: 100%;
resize: vertical;
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../styles/generic.scss%22,%22../styles/mixins/_foundry.scss%22,%22../styles/_vars.scss%22,%22../styles/mixins/_partials.scss%22,%22../styles/global/icons.scss%22,%22../styles/global/buttons.scss%22,%22../styles/sheets/partials/stat.scss%22,%22../styles/sheets/partials/skill.scss%22,%22../styles/sheets/partials/panel.scss%22,%22../styles/mixins/_breakpoints.scss%22,%22../styles/sheets/actor/mvp.scss%22,%22../styles/sheets/actor/mob.scss%22,%22../styles/sheets/actor/sync/basic.scss%22,%22../styles/sheets/items/aspect.scss%22,%22../styles/sheets/items/spell.scss%22,%22../styles/sheets/items/pet.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAIQ;AAKP;EACC;;AAED;EACC;;AAGD;ECfA;EACA;EACA;EDeC,aEhBW;EFiBX;;AAGD;EACC;;AAGD;ECzBA;EACA;EACA;EDyBC;EACA;;AAEA;EACC;;AAIF;AAAA;AAAA;EAGC;EGpCD;EACA;EACA;EACA;EACA;EACA,aDLW;;ACOX;AAAA;AAAA;AAAA;AAAA;EAEC;;AH+BD;EACC;;AAGD;EACC;;AAEA;EACC;;;AAMH;EACC;;AAEA;EACC;EACA,YEzDW;;AF2DX;EACC;EACA,aE/DS;EFgET;;;AIhEF;EACC;EACA;EACA;;AAIC;EACC;EACA;;AAFD;EACC;EACA;;AAFD;EACC;EACA;;AAFD;EACC;EACA;;AAFD;EACC;EACA;;AAFD;EACC;EACA;;AAFD;EACC;EACA;;;ACTH;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC,YHXc;EGYd,OHXe;;AGYf;EACC;EACA,OHfa;EGgBb,cHhBa;;AGoBf;EACC,YHlBc;EGmBd,OHlBe;;AGmBf;EACC;EACA,OHtBa;EGuBb,cHvBa;;AG2Bf;EACC,YHzBa;EG0Bb,OHzBc;;AG0Bd;EACC;EACA,OH7BY;EG8BZ,cH9BY;;AGkCd;EACC;;AAID;EACC;;AACA;EACC;;;ACvDJ;EACC;EACA;EACA;;ACHD;EACC;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;;;ACdH;EACC;EACA;EAEA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EPlBD;EACA;EACA;EOkBE;EACA;EACA,aNrBU;EMsBV;;AAGD;EAEC,QADO;EAEP,OAFO;EAGP;;AAIF;EACC;;;AC7BD;EDkCA;IACC;IACA;;;AExCF;EACC;EACA,qBACC;EASD;EACA,oBACC;EAGD;EACA;;AAEA;EACC;EACA;EACA;EACA;;AAEA;EACC;;AAIA;EACC;;AAMF;EACC;;AACA;EACC;EACA;;AAGD;EACC;;AAGF;EACC;;AACA;EACC;EACA;EACA;EACA;EACA;EACA;;AAGF;EACC;;AAEA;EACC;EACA;EACA;EACA;;AAGF;EACC;;AAEA;EACC;EACA;EACA;;AAED;EACC;EACA;;AAED;EACC;;AAGD;EACC;EACA;EACA;;AAGD;AAAA;AAAA;EAGC;EACA;;AAGD;EACC;;AAGF;EACC;;AAEA;EACC;EACA;EACA;;AAGD;AAAA;EAEC;EACA;EACA;;AAEA;AAAA;EACC;;AAIF;EACC;EACA;;AAGF;EACC;;AACA;EACC;EACA;EACA;EACA;;AAEA;EACC;;AAKD;EACC;EACA;EACA;;AAEA;EACC;;AAKJ;EACC;;AAEA;EACC;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;;AAEA;EACC;;AAGF;EACC;EACA;EACA;;AAED;EACC;EACA;EACA;;AAED;EACC;EACA;EACA;EACA;;AAIH;EACC;;AACA;EACC;EACA;EACA;EACA;;AAEA;EACC;;AAIH;EACC;;AAEA;EACC;EACA;EACA;;AAEA;EACC;;AAIF;EACC;EACA;EACA;;AAGF;EACC;;AAED;EACC;;AAEA;EACC;EACA;EACA;;AAEA;EACC;;AAIH;EACC;;AAIF;EACC;EACA;EACA;EACA;;AAIA;EACC;;;AD9PF;ECsQC;IACC;IACA;IACA,qBACC;;EAkBC;IACC;;EAKD;IACC;IACA;;;AD9RL;ECwSC;IACC;IACA;IACA,qBACC;;EAeC;IACC;;;ACjUN;EACC;;AAEA;EACC;EACA;;;ACJD;EACC;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;;AAGD;EACC;EACA;;AAGD;EACC;EACA;;AAMA;EACC;EACA;;;AHlBH;EG4BG;IACC;IACA;;;ACzCL;EACC;;AAEA;EACC;EACA;EACA;;AAGD;EACC;EACA;;;ACXF;EACC;;AAEA;EACC;EACA;EACA;;AAGD;EACC;EACA;;;ACXF;EACC;;AAEA;EACC;EACA;EACA;;AAGD;EACC;EACA%22,%22file%22:%22root.css%22%7D */

View file

@ -1,9 +0,0 @@
.dotdungeon .actor--mob {
padding: 4px;
}
.dotdungeon .actor--mob textarea {
width: 100%;
resize: vertical;
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../../../styles/sheets/actor/mob.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAEA;EACC;;AAEA;EACC;EACA%22,%22file%22:%22mob.css%22%7D */

View file

@ -1,236 +0,0 @@
.dotdungeon .actor--pc {
display: grid;
grid-template-areas: "profile stats stats" "profile skills skills" "sync skills skills" "spells weapons aspect" "spells weapons aspect" "backpack roles mounts" "backpack roles mounts" "pets storage storage" "pets storage storage";
grid-template-columns: repeat(3, minmax(0, 1fr));
grid-template-rows: min-content 1fr repeat(7, min-content);
padding: 4px;
gap: 4px;
}
.dotdungeon .actor--pc details {
border-radius: 4px;
background-color: rgba(0, 0, 0, 0.2);
padding: 4px;
margin-bottom: 8px;
}
.dotdungeon .actor--pc details summary {
cursor: pointer;
}
.dotdungeon .actor--pc details[open] .expanded-rotate {
transform: rotate(90deg);
}
.dotdungeon .actor--pc .panel--profile {
grid-area: profile;
}
.dotdungeon .actor--pc .panel--profile .avatar {
width: 100%;
aspect-ratio: 1/1;
}
.dotdungeon .actor--pc .panel--profile label, .dotdungeon .actor--pc .panel--profile input {
width: 100%;
}
.dotdungeon .actor--pc .panel--stats {
grid-area: stats;
}
.dotdungeon .actor--pc .panel--stats .panel__content {
display: flex;
flex-direction: row;
gap: 8px;
justify-content: space-evenly;
padding: 8px;
flex-wrap: wrap;
}
.dotdungeon .actor--pc .panel--skills {
grid-area: skills;
}
.dotdungeon .actor--pc .panel--skills .panel__content {
display: grid;
row-gap: 8px;
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-template-rows: repeat(2, minmax(0, min-content));
}
.dotdungeon .actor--pc .panel--backpack {
grid-area: backpack;
}
.dotdungeon .actor--pc .panel--backpack .row {
display: flex;
flex-direction: row;
align-items: center;
}
.dotdungeon .actor--pc .panel--backpack .col {
display: flex;
flex-direction: column;
}
.dotdungeon .actor--pc .panel--backpack .grow {
flex-grow: 1;
}
.dotdungeon .actor--pc .panel--backpack .panel__content {
display: flex;
flex-direction: column;
gap: 4px;
}
.dotdungeon .actor--pc .panel--backpack .bytes-input,
.dotdungeon .actor--pc .panel--backpack .supplies-count,
.dotdungeon .actor--pc .panel--backpack .materials-count {
width: 25%;
text-align: center;
}
.dotdungeon .actor--pc .panel--backpack textarea {
resize: vertical;
}
.dotdungeon .actor--pc .panel--sync {
grid-area: sync;
}
.dotdungeon .actor--pc .panel--sync .panel__content {
display: flex;
flex-direction: column;
gap: 4px;
}
.dotdungeon .actor--pc .panel--sync .respawns,
.dotdungeon .actor--pc .panel--sync .sync {
display: flex;
flex-direction: row;
align-items: center;
}
.dotdungeon .actor--pc .panel--sync .respawns__header,
.dotdungeon .actor--pc .panel--sync .sync__header {
flex-grow: 1;
}
.dotdungeon .actor--pc .panel--sync .sync__input {
width: 80px;
margin: 3px 5px;
}
.dotdungeon .actor--pc .panel--aspect {
grid-area: aspect;
}
.dotdungeon .actor--pc .panel--aspect .panel__content {
display: grid;
grid-template-rows: min-content min-content;
gap: 4px;
text-align: center;
}
.dotdungeon .actor--pc .panel--aspect .panel__content textarea {
resize: vertical;
}
.dotdungeon .actor--pc .panel--aspect .aspect__used {
display: flex;
align-items: center;
gap: 4px;
}
.dotdungeon .actor--pc .panel--aspect .aspect__used--input {
margin: 0;
}
.dotdungeon .actor--pc .panel--weapons {
grid-area: weapons;
}
.dotdungeon .actor--pc .panel--weapons .weapon {
margin-top: 4px;
display: flex;
flex-direction: column;
gap: 4px;
}
.dotdungeon .actor--pc .panel--weapons .weapon__name {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.dotdungeon .actor--pc .panel--weapons .weapon__name input {
width: 50%;
}
.dotdungeon .actor--pc .panel--weapons .weapon__group {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4px;
}
.dotdungeon .actor--pc .panel--weapons .weapon__ammo-type, .dotdungeon .actor--pc .panel--weapons .weapon__damage-type {
display: flex;
flex-direction: column;
align-items: center;
}
.dotdungeon .actor--pc .panel--weapons .weapon__is-scoped, .dotdungeon .actor--pc .panel--weapons .weapon__is-ranged {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.dotdungeon .actor--pc .panel--roles {
grid-area: roles;
}
.dotdungeon .actor--pc .panel--roles .panel__content {
display: grid;
grid-template-rows: repeat(4, min-content);
height: 100%;
gap: 4px;
}
.dotdungeon .actor--pc .panel--roles .panel__content textarea {
resize: vertical;
}
.dotdungeon .actor--pc .panel--spells {
grid-area: spells;
}
.dotdungeon .actor--pc .panel--spells .spell {
display: flex;
flex-direction: column;
gap: 4px;
}
.dotdungeon .actor--pc .panel--spells .spell .placeholder {
opacity: 75%;
}
.dotdungeon .actor--pc .panel--spells .panel__content {
display: flex;
gap: 4px;
flex-direction: column;
}
.dotdungeon .actor--pc .panel--mounts {
grid-area: mounts;
}
.dotdungeon .actor--pc .panel--pets {
grid-area: pets;
}
.dotdungeon .actor--pc .panel--pets .panel__content {
display: grid;
grid-template-rows: min-content min-content;
gap: 4px;
}
.dotdungeon .actor--pc .panel--pets .panel__content textarea {
resize: vertical;
}
.dotdungeon .actor--pc .panel--storage {
grid-area: storage;
}
.dotdungeon .actor--pc .actions {
display: flex;
flex-direction: row;
justify-content: end;
gap: 4px;
}
.dotdungeon .actor--pc .panel__content .center {
text-align: center;
}
@container (max-width: 620px) {
.dotdungeon .actor--pc {
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-template-rows: repeat(15, min-content);
grid-template-areas: "profile stats" "profile skills" "sync skills" "weapons skills" "weapons skills" "backpack aspect" "backpack aspect" "backpack roles" "backpack roles" "backpack roles" "backpack spells" "pets spells" "pets storage" "mounts storage" "mounts storage";
}
.dotdungeon .actor--pc .panel--stats .panel__content {
flex-wrap: wrap;
}
.dotdungeon .actor--pc .panel--skills .panel__content {
display: flex;
flex-direction: column;
}
}
@container (max-width: 400px) {
.dotdungeon .actor--pc {
grid-template-columns: 1fr;
grid-template-rows: repeat(12, min-content);
grid-template-areas: "profile" "stats" "sync" "skills" "aspect" "roles" "backpack" "weapons" "spells" "mounts" "pets" "storage";
}
.dotdungeon .actor--pc .panel--skills .skill {
flex-direction: column;
}
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../../../styles/sheets/actor/mvp.scss%22,%22../../../styles/mixins/_breakpoints.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAGA;EACC;EACA,qBACC;EASD;EACA,oBACC;EAGD;EACA;;AAEA;EACC;EACA;EACA;EACA;;AAEA;EACC;;AAIA;EACC;;AAMF;EACC;;AACA;EACC;EACA;;AAGD;EACC;;AAGF;EACC;;AACA;EACC;EACA;EACA;EACA;EACA;EACA;;AAGF;EACC;;AAEA;EACC;EACA;EACA;EACA;;AAGF;EACC;;AAEA;EACC;EACA;EACA;;AAED;EACC;EACA;;AAED;EACC;;AAGD;EACC;EACA;EACA;;AAGD;AAAA;AAAA;EAGC;EACA;;AAGD;EACC;;AAGF;EACC;;AAEA;EACC;EACA;EACA;;AAGD;AAAA;EAEC;EACA;EACA;;AAEA;AAAA;EACC;;AAIF;EACC;EACA;;AAGF;EACC;;AACA;EACC;EACA;EACA;EACA;;AAEA;EACC;;AAKD;EACC;EACA;EACA;;AAEA;EACC;;AAKJ;EACC;;AAEA;EACC;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;;AAEA;EACC;;AAGF;EACC;EACA;EACA;;AAED;EACC;EACA;EACA;;AAED;EACC;EACA;EACA;EACA;;AAIH;EACC;;AACA;EACC;EACA;EACA;EACA;;AAEA;EACC;;AAIH;EACC;;AAEA;EACC;EACA;EACA;;AAEA;EACC;;AAIF;EACC;EACA;EACA;;AAGF;EACC;;AAED;EACC;;AAEA;EACC;EACA;EACA;;AAEA;EACC;;AAIH;EACC;;AAIF;EACC;EACA;EACA;EACA;;AAIA;EACC;;;AC9PF;EDsQC;IACC;IACA;IACA,qBACC;;EAkBC;IACC;;EAKD;IACC;IACA;;;AC9RL;EDwSC;IACC;IACA;IACA,qBACC;;EAeC;IACC%22,%22file%22:%22mvp.css%22%7D */

View file

@ -1,19 +0,0 @@
.dotdungeon .actor--sync {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.dotdungeon .actor--sync .sync-input {
width: 30%;
text-align: center;
}
@container (max-width: 400px) {
.dotdungeon--sync-sheet header .configure-sheet,
.dotdungeon--sync-sheet header .configure-token {
display: none;
}
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../../../styles/sheets/actor/sync.scss%22,%22../../../styles/mixins/_breakpoints.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAGC;EACC;EACA;EACA;EACA;;AAEA;EACC;EACA;;;ACJF;EDaG;AAAA;IAEC%22,%22file%22:%22sync.css%22%7D */

View file

@ -1,33 +0,0 @@
.dotdungeon .actor--basic-sync {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
gap: 4px;
}
.dotdungeon .actor--basic-sync label {
display: flex;
flex-direction: column;
align-items: center;
}
.dotdungeon .actor--basic-sync .sync-input {
width: 30%;
text-align: center;
}
.dotdungeon .actor--basic-sync .name-input {
width: 60%;
text-align: center;
}
.dotdungeon--sync-sheet header .configure-token {
display: none;
visibility: hidden;
}
@container (max-width: 300px) {
.dotdungeon--sync-sheet header .configure-sheet {
display: none;
visibility: hidden;
}
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../../../../styles/sheets/actor/sync/basic.scss%22,%22../../../../styles/mixins/_breakpoints.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAGC;EACC;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;;AAGD;EACC;EACA;;AAGD;EACC;EACA;;AAMA;EACC;EACA;;;AClBH;ED4BG;IACC;IACA%22,%22file%22:%22basic.css%22%7D */

View file

@ -1,14 +0,0 @@
.dotdungeon .item--aspect {
padding: 4px;
}
.dotdungeon .item--aspect input[type=text] {
font-size: 1.5em;
height: 1.5em;
width: 100%;
}
.dotdungeon .item--aspect textarea {
width: 100%;
resize: vertical;
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../../../styles/sheets/items/aspect.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAEA;EACC;;AAEA;EACC;EACA;EACA;;AAGD;EACC;EACA%22,%22file%22:%22aspect.css%22%7D */

View file

@ -1,14 +0,0 @@
.dotdungeon .item--pet {
padding: 4px;
}
.dotdungeon .item--pet input[type=text] {
font-size: 1.5em;
height: 1.5em;
width: 100%;
}
.dotdungeon .item--pet textarea {
width: 100%;
resize: vertical;
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../../../styles/sheets/items/pet.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAEA;EACC;;AAEA;EACC;EACA;EACA;;AAGD;EACC;EACA%22,%22file%22:%22pet.css%22%7D */

View file

@ -1,14 +0,0 @@
.dotdungeon .item--spell {
padding: 4px;
}
.dotdungeon .item--spell input[type=text] {
font-size: 1.5em;
height: 1.5em;
width: 100%;
}
.dotdungeon .item--spell textarea {
width: 100%;
resize: vertical;
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../../../styles/sheets/items/spell.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAEA;EACC;;AAEA;EACC;EACA;EACA;;AAGD;EACC;EACA%22,%22file%22:%22spell.css%22%7D */

View file

@ -1,40 +0,0 @@
.dotdungeon .panel {
display: grid;
grid-template-rows: min-content 1fr;
border: 2px solid black;
}
.dotdungeon .panel__header {
background: black;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 4px;
padding: 0 4px;
}
.dotdungeon .panel__header h2 {
all: initial;
display: block;
box-sizing: border-box;
color: white;
flex-grow: 1;
font-family: "Pixelify Sans", sans-serif;
font-size: 20px;
}
.dotdungeon .panel__header .icon {
height: 20px;
width: 20px;
aspect-ratio: 1/1;
}
.dotdungeon .panel__content {
padding: 8px;
}
@container (max-width: 400px) {
.dotdungeon .panel__header .icon {
display: none;
visibility: hidden;
}
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../../../styles/sheets/partials/panel.scss%22,%22../../../styles/mixins/_foundry.scss%22,%22../../../styles/_vars.scss%22,%22../../../styles/mixins/_breakpoints.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAIA;EACC;EACA;EAEA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EClBD;EACA;EACA;EDkBE;EACA;EACA,aErBU;EFsBV;;AAGD;EAEC,QADO;EAEP,OAFO;EAGP;;AAIF;EACC;;;AG7BD;EHkCA;IACC;IACA%22,%22file%22:%22panel.css%22%7D */

View file

@ -1,22 +0,0 @@
.dotdungeon .skill {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 100%;
gap: 8px;
}
.dotdungeon .skill-group {
display: flex;
flex-direction: column;
justify-content: center;
gap: 4px;
}
.dotdungeon .skill-group h3 {
margin-top: 8px;
font-size: 1.2em;
width: 100%;
text-align: center;
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../../../styles/sheets/partials/skill.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAAA;EACC;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA%22,%22file%22:%22skill.css%22%7D */

View file

@ -1,7 +0,0 @@
.dotdungeon .stat {
display: flex;
flex-direction: column;
align-items: center;
}
/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../../../styles/sheets/partials/stat.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAAA;EACC;EACA;EACA%22,%22file%22:%22stat.css%22%7D */

27
.vscode/components.html-data.json vendored Normal file
View file

@ -0,0 +1,27 @@
{
"version": 1.1,
"tags": [
{
"name": "dd-incrementer",
"description": "A number input that allows more flexible increase/decrease buttons",
"attributes": [
{ "name": "value", "description": "The initial value to put in the input" },
{ "name": "name", "description": "The form name to use when this input is used to submit data" },
{ "name": "min", "description": "The minimum value that this input can contain" },
{ "name": "max", "description": "The maximum value that this input can contain" },
{ "name": "smallStep", "description": "The value that the input is changed by when clicking a delta button or using the up/down arrow key" },
{ "name": "largeStep", "description": "The value that the input is changed by when clicking a delta button with control held or using the page up/ page down arrow key" }
]
},
{
"name": "dd-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 dotdungeon system" },
{ "name": "path", "description": "The full path of the icon, this will only be used if `name` isn't provided or fails to fetch." }
]
}
],
"globalAttributes": [],
"valueSets": []
}

16
.vscode/settings.json vendored
View file

@ -1,11 +1,19 @@
{
"files.autoSave": "onWindowChange",
"editor.tabSize": 2,
"[javascript]": {
"editor.tabSize": 4
},
"[yaml,yml]": {
"editor.insertSpaces": true,
"editor.tabSize": 2
}
},
"git.branchProtection": [],
"files.exclude": {
"dotdungeon.lock": true,
".styles": true,
"node_modules": true,
"packs": true,
".gitattributes": true,
},
"html.customData": [
"./.vscode/components.html-data.json"
]
}

View file

@ -1,7 +0,0 @@
1. Make sure that the `version` is the correct version number.
2. Copy the `system.json` in order to make the version-specific manifest
3. Update the `download` to point to the version-specific file from Github
4. Compress all of the necessary files and folders
5. Create the release on Github with the correct tag being created
6. Upload the compressed files and the version-specific manifest file
7. Save the release as draft, prerelease, or stable (pre-releases won't be caught in the `/latest` URL that is used to check for updates)

View file

@ -1,2 +0,0 @@
- "Resources" and "Supplies" are used interchangeably in the book
-

29
TODO
View file

@ -1,29 +0,0 @@
## MVP:
- Text-box PC Character sheet
- PC Data Structure
- Dice Rolling
## Full Release
- Data Models:
- Actors:
- NPC
- PC
- Mob
- Items:
- Weapons
- Armour
- Equipment
- Foil
- Pet
- Transportation
- Structure
- Service
- Legendary Items
- Spells
- Aspects
- Status
- Roles
- Character Sheet:
- PC
- NPC
- Mob

View file

@ -1,3 +0,0 @@
<svg width="100%" height="100%" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<path d="m82.137 50.016c-0.003907 2.6133-1.1172 5.1055-3.0664 6.8477l-44.16 40.445c-1.8984 1.75-4.3867 2.7227-6.9688 2.7266-1.4727 0-2.9297-0.30859-4.2773-0.90234-3.5078-1.4531-5.7969-4.875-5.8008-8.668v-80.93c0.019531-3.7812 2.3047-7.1875 5.8008-8.6367 3.7734-1.6836 8.1836-0.98047 11.246 1.793l44.172 40.457c1.9492 1.75 3.0625 4.25 3.0547 6.8672z"/>
</svg>

Before

Width:  |  Height:  |  Size: 484 B

View file

@ -1,3 +0,0 @@
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<path d="M 61.24 9 L 42.776 9 C 21.393 9 4.095 26.336 4.095 47.679 C 2.013 74.103 34.856 91.236 48.486 97.153 C 51.236 98.362 54.278 96.319 54.278 93.319 L 54.278 84.775 C 54.278 82.482 56.154 80.606 58.447 80.606 L 61.197 80.606 C 80.995 80.606 97 64.561 97 44.804 C 97 25.046 80.954 9 61.197 9 L 61.24 9 Z M 32.854 54.389 C 29.813 54.389 27.354 51.93 27.354 48.888 C 27.354 45.844 29.813 43.388 32.854 43.388 C 35.899 43.388 38.358 45.844 38.358 48.888 C 38.358 51.93 35.899 54.389 32.854 54.389 Z M 50.527 54.389 C 47.486 54.389 45.025 51.93 45.025 48.888 C 45.025 45.844 47.486 43.388 50.527 43.388 C 53.571 43.388 56.03 45.844 56.03 48.888 C 56.03 51.93 53.571 54.389 50.527 54.389 Z M 68.202 54.389 C 65.158 54.389 62.697 51.93 62.697 48.888 C 62.697 45.844 65.158 43.388 68.202 43.388 C 71.242 43.388 73.703 45.844 73.703 48.888 C 73.703 51.93 71.242 54.389 68.202 54.389 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 975 B

View file

@ -1,3 +0,0 @@
<svg width="100%" height="100%" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="m96.293 83.457c3.543 3.5469 3.543 9.2891 0 12.836-3.5469 3.543-9.2891 3.543-12.836 0l-31.992-31.992c-0.80859-0.8125-2.1211-0.8125-2.9297 0l-31.992 31.992c-3.5469 3.543-9.2891 3.543-12.836 0-3.543-3.5469-3.543-9.2891 0-12.836l31.992-31.988c0.8125-0.8125 0.8125-2.125 0-2.9336l-31.992-31.992c-3.543-3.5469-3.543-9.2891 0-12.836 3.5469-3.543 9.2891-3.543 12.836 0l31.992 31.996c0.80859 0.80859 2.1211 0.80859 2.9297 0l31.992-31.996c3.5469-3.543 9.2891-3.543 12.836 0 3.543 3.5469 3.543 9.2891 0 12.836l-31.992 31.992c-0.8125 0.80859-0.8125 2.1211 0 2.9336z"/>
</svg>

Before

Width:  |  Height:  |  Size: 678 B

View file

@ -1,3 +1 @@
<svg width="100%" height="100%" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="m52.348 11.457c-1.1094-0.91797-2.7305-0.91797-3.8398 0l-36.531 30.484c-0.67969 0.57031-1.0781 1.4102-1.0781 2.3008v10.949c0 0.87891 0.39062 1.7188 1.0586 2.2891l36.535 31.043c0.55859 0.48047 1.25 0.71094 1.9414 0.71094s1.3789-0.23828 1.9414-0.71094l36.742-31.043c0.66797-0.57031 1.0586-1.4102 1.0586-2.2891l-0.003906-10.941c0-0.89062-0.39844-1.7383-1.0781-2.3086zm31.824 39.934-15.445-3.9297-10.316-23.188 25.773 21.387zm-33.73 3.5195-12.258-6.2891 12.258-27.496 12.258 27.496zm-16.508-1.7227 13.508 6.9297v19.637l-27.176-23.086zm19.504 6.9297 13.508-6.9297 13.797 3.5195-27.305 23.066zm-10.996-35.773-10.297 23.105-15.246 3.8906v-5.6797z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M52.348 11.457a3.021 3.021 0 0 0-3.84 0l-36.53 30.484a3.005 3.005 0 0 0-1.079 2.3v10.95c0 .879.39 1.719 1.059 2.289l36.535 31.043a3.01 3.01 0 0 0 3.883 0L89.118 57.48a3.02 3.02 0 0 0 1.058-2.29l-.004-10.94c0-.89-.398-1.739-1.078-2.309zm31.824 39.934-15.445-3.93-10.316-23.188L84.184 45.66zm-33.73 3.52-12.258-6.29 12.258-27.496L62.7 48.621zm-16.508-1.723 13.508 6.93v19.636L20.266 56.668zm19.504 6.93 13.508-6.93 13.797 3.52-27.305 23.065zM42.442 24.343 32.145 47.45 16.899 51.34v-5.68z"/></svg>

Before

Width:  |  Height:  |  Size: 763 B

After

Width:  |  Height:  |  Size: 566 B

Before After
Before After

View file

@ -1,3 +1 @@
<svg width="100%" height="100%" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="m85.484 37.672-12.418-17.098c-0.37109-0.51172-0.89844-0.89062-1.5-1.0898l-20.098-6.5273c-0.60156-0.19922-1.25-0.19922-1.8516 0l-20.098 6.5273c-0.60156 0.19922-1.1289 0.57812-1.5 1.0898l-12.422 17.098c-0.37109 0.51172-0.57031 1.1289-0.57031 1.7578v21.125c0 0.62891 0.19922 1.25 0.57031 1.7578l12.418 17.098c0.37109 0.51172 0.89844 0.89062 1.5 1.0898l20.098 6.5273c0.30078 0.10156 0.60938 0.14844 0.92969 0.14844 0.32031 0 0.62891-0.050781 0.92969-0.14844l20.098-6.5273c0.60156-0.19922 1.1289-0.57812 1.5-1.0898l12.414-17.094c0.37109-0.51172 0.57031-1.1289 0.57031-1.7578v-21.125c0-0.63281-0.20313-1.25-0.57031-1.7617zm-7.0586 0.49219-9.3398 4.0078-15.547-11.297v-10.93l15.238 4.9492zm-18.836 25.793h-18.098l-5.5898-17.207 14.637-10.637 14.637 10.637zm-27.297-39.062 15.238-4.9492v10.938l-15.539 11.289-9.3398-4.0078zm-11.266 34.695v-15.598l8.918 3.8281 6.0078 18.484-5.3477 6.457zm29.512 21.445-14.969-4.8594 5.1484-6.2188h19.625l5.1484 6.2188zm19.938-8.2695-5.3477-6.457 6.0078-18.484 8.918-3.8281v15.598z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M85.484 37.672 73.066 20.574a3.024 3.024 0 0 0-1.5-1.09l-20.098-6.527c-.602-.2-1.25-.2-1.852 0l-20.098 6.527c-.601.2-1.128.578-1.5 1.09L15.596 37.672a2.998 2.998 0 0 0-.57 1.758v21.125c0 .629.2 1.25.57 1.758L28.014 79.41c.371.511.899.89 1.5 1.09l20.098 6.527a2.988 2.988 0 0 0 1.86 0L71.57 80.5a3.024 3.024 0 0 0 1.5-1.09l12.414-17.093c.37-.512.57-1.13.57-1.758V39.434c0-.633-.203-1.25-.57-1.762zm-7.059.492-9.34 4.008L53.54 30.875v-10.93l15.238 4.95zM59.59 63.957H41.491l-5.59-17.207L50.54 36.113 65.176 46.75zM32.292 24.895l15.238-4.949v10.938L31.991 42.173l-9.34-4.008zM21.026 59.59V43.992l8.918 3.828 6.008 18.484-5.347 6.457zm29.512 21.445-14.969-4.86 5.149-6.218h19.625l5.148 6.219zm19.938-8.27L65.13 66.31l6.007-18.484 8.919-3.828v15.598z"/></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 825 B

Before After
Before After

View file

@ -1,3 +1 @@
<svg width="100%" height="100%" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="m82.172 32.355c-0.019531-0.14844-0.03125-0.30078-0.070313-0.44141-0.039062-0.12891-0.10156-0.23828-0.14844-0.37109-0.039063-0.10938-0.070313-0.21875-0.12891-0.32031-0.011719-0.011718-0.019531-0.019531-0.019531-0.03125-0.070313-0.10938-0.16016-0.21094-0.23828-0.32031-0.078125-0.10156-0.14844-0.21094-0.23828-0.30078-0.078125-0.078124-0.17969-0.14062-0.26953-0.21094-0.10938-0.089844-0.21875-0.19141-0.35156-0.26172-0.019531-0.011718-0.03125-0.019531-0.039062-0.03125l-29.312-16.195c-0.94141-0.51953-2.0781-0.5-3 0.058594l-28.676 17.297c-0.019532 0.011719-0.03125 0.03125-0.050782 0.039063-0.12109 0.070313-0.21875 0.17188-0.32812 0.26172-0.089843 0.078125-0.19141 0.14844-0.28125 0.23828-0.078125 0.089844-0.14844 0.19922-0.21875 0.28906-0.078125 0.10937-0.17188 0.21875-0.23047 0.33984-0.011718 0.019531-0.019531 0.03125-0.03125 0.039063-0.050781 0.10156-0.070312 0.19922-0.10156 0.30078-0.050781 0.12891-0.10938 0.25-0.14062 0.39062s-0.039063 0.28125-0.050781 0.41797c-0.011719 0.10156-0.039063 0.19922-0.039063 0.30859l0.62891 33.484c0.019531 1.0703 0.60937 2.0508 1.5508 2.5703l29.332 16.207c0.44922 0.25 0.94922 0.37109 1.4492 0.37109 0.53906 0 1.0703-0.14062 1.5508-0.42969l28.684-17.285c0.91797-0.55078 1.4688-1.5508 1.4492-2.6289l-0.62891-33.484c0-0.10156-0.039062-0.20312-0.050781-0.30078zm-21.926 27.652-8.8789 15.816-9.4688-15.477zm-18.926-6.1992 8.8789-15.816 9.4688 15.477zm-5.3594-2.707-9.4375-14.605 18.258-1.1094zm29.305 0.027344-9.7578-15.945 18.617 0.41797zm-12.215-22.004-0.089843-7.4883 14.129 7.8086zm-6 0.10938-13.828 0.83984 13.746-8.2891zm-14.969 26.914-7.3398 5.3398-0.32813-17.195zm3.2891 5.0195 9.3867 15.348-17.336-9.5781zm31.105-0.011719 7.707 4.9609-15.848 9.5469zm2.9609-5.2383 6.9883-12.258 0.32031 16.965z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M82.172 32.355c-.02-.148-.031-.3-.07-.441-.04-.13-.102-.239-.149-.372-.039-.109-.07-.218-.129-.32-.011-.012-.02-.02-.02-.031-.07-.11-.16-.211-.237-.32-.079-.102-.149-.211-.239-.301-.078-.078-.18-.14-.27-.211-.109-.09-.218-.192-.35-.262a.113.113 0 0 1-.04-.031L51.356 13.87a2.985 2.985 0 0 0-3 .059L19.68 31.227c-.02.011-.031.03-.05.039-.122.07-.22.171-.329.261-.09.078-.191.149-.281.239-.078.09-.148.199-.219.289-.078.109-.172.218-.23.34a.113.113 0 0 1-.032.039c-.05.101-.07.199-.101.3-.05.13-.11.25-.14.391s-.04.281-.051.418c-.012.101-.04.2-.04.309l.63 33.484c.019 1.07.609 2.05 1.55 2.57L49.72 86.113c.45.25.95.37 1.45.37.538 0 1.07-.14 1.55-.429L81.403 68.77a2.994 2.994 0 0 0 1.45-2.629l-.63-33.484c0-.101-.039-.203-.05-.3zM60.246 60.007l-8.879 15.816-9.469-15.477zm-18.926-6.2 8.879-15.815 9.469 15.477zm-5.36-2.706-9.437-14.605 18.258-1.11zm29.306.027-9.758-15.945 18.617.418zM53.05 29.124l-.09-7.488 14.129 7.808zm-6 .11-13.828.84 13.746-8.29zM32.08 56.148l-7.34 5.34-.327-17.196zm3.29 5.019 9.386 15.348-17.336-9.578zm31.105-.012 7.707 4.961-15.848 9.547zm2.96-5.238 6.989-12.258.32 16.965z"/></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

View file

@ -1,3 +1 @@
<svg width="100%" height="100%" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="m52.91 11.938c-0.57031-0.73828-1.4492-1.168-2.3789-1.168s-1.8086 0.42969-2.3789 1.168l-37.773 48.949c-0.51953 0.66797-0.73047 1.5312-0.57812 2.3711 0.14844 0.82813 0.64844 1.5703 1.3711 2.0078l37.781 23.516c0.48828 0.30078 1.0391 0.44922 1.5898 0.44922s1.1016-0.14844 1.5898-0.44922l37.781-23.516c0.71875-0.44922 1.2188-1.1797 1.3711-2.0078 0.14844-0.82812-0.058594-1.6914-0.57812-2.3711zm-5.3711 10.629v58.277l-30.383-18.918zm6 58.266v-58.266l30.383 39.363z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M52.91 11.938a3.005 3.005 0 0 0-4.758 0L10.38 60.887a2.993 2.993 0 0 0-.578 2.371c.149.828.649 1.57 1.371 2.008l37.781 23.516a3.028 3.028 0 0 0 3.18 0l37.78-23.516a3.02 3.02 0 0 0 1.372-2.008 3.03 3.03 0 0 0-.578-2.371zm-5.371 10.629v58.277L17.156 61.926zm6 58.266V22.567L83.922 61.93z"/></svg>

Before

Width:  |  Height:  |  Size: 583 B

After

Width:  |  Height:  |  Size: 365 B

Before After
Before After

View file

@ -1,3 +1 @@
<svg width="100%" height="100%" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="m83.664 28.203-31.953-13.527c-0.75-0.32031-1.5898-0.32031-2.3398 0l-31.953 13.527c-1.1016 0.46875-1.8203 1.5508-1.8281 2.7383v0.019532 37.602c0 1.1914 0.71094 2.2695 1.8008 2.75l31.953 13.996c0.37891 0.17188 0.78906 0.25 1.1992 0.25 0.41016 0 0.82031-0.078125 1.1992-0.25l31.953-13.996c1.0898-0.48047 1.8008-1.5586 1.8008-2.75l-0.003906-37.598v-0.019532c-0.007813-1.1914-0.71875-2.2695-1.8281-2.7422zm-33.125-7.5078 24.375 10.316-24.375 10.68-24.375-10.676zm-28.965 14.859 25.965 11.367v31.055l-25.965-11.371zm31.965 42.418v-31.051l25.953-11.367v31.055z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M83.664 28.203 51.711 14.676c-.75-.32-1.59-.32-2.34 0L17.418 28.203a3.006 3.006 0 0 0-1.828 2.738v37.622c0 1.191.711 2.27 1.8 2.75l31.954 13.996c.379.172.789.25 1.2.25.41 0 .82-.078 1.198-.25l31.953-13.996a3.012 3.012 0 0 0 1.801-2.75l-.004-37.598v-.02a3 3 0 0 0-1.828-2.742zm-33.125-7.508 24.375 10.316-24.375 10.68-24.375-10.676zm-28.965 14.86L47.539 46.92v31.055l-25.965-11.37zm31.965 42.417v-31.05l25.953-11.368V66.61z"/></svg>

Before

Width:  |  Height:  |  Size: 678 B

After

Width:  |  Height:  |  Size: 502 B

Before After
Before After

View file

@ -1,3 +1 @@
<svg width="100%" height="100%" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="m80.785 31.625-28.047-16.949c-0.91797-0.55078-2.0586-0.57812-3-0.058593l-28.691 15.809c-0.94141 0.51953-1.5312 1.5-1.5508 2.5703l-0.64844 32.762c-0.019531 1.0703 0.53125 2.0703 1.4492 2.6289l28.043 16.945c0.48047 0.28906 1.0117 0.42969 1.5508 0.42969 0.5 0 1-0.12109 1.4492-0.37109l28.695-15.816c0.94141-0.51953 1.5312-1.5 1.5508-2.5703l0.64844-32.762c0.019531-1.0703-0.53125-2.0703-1.4492-2.6172zm-4.9688 23.793-17.156-30.164 17.535 10.598zm-2.4102 7.9102-45.199-0.44922 22.566-39.363zm-30.543-38.074-17.828 31.094 0.42969-21.504zm7.0859 54.039-17.164-10.367 35.352 0.35156z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M80.785 31.625 52.738 14.676a3.004 3.004 0 0 0-3-.059l-28.691 15.81a2.999 2.999 0 0 0-1.55 2.57l-.65 32.762a3.013 3.013 0 0 0 1.45 2.629L48.34 85.333c.48.289 1.012.43 1.55.43.5 0 1-.122 1.45-.372l28.695-15.816a2.999 2.999 0 0 0 1.55-2.57l.65-32.762a2.98 2.98 0 0 0-1.45-2.617zm-4.969 23.793L58.66 25.254l17.535 10.598zm-2.41 7.91-45.199-.449 22.566-39.363zM42.863 25.254 25.035 56.348l.43-21.504zm7.086 54.04L32.785 68.925l35.352.352z"/></svg>

Before

Width:  |  Height:  |  Size: 700 B

After

Width:  |  Height:  |  Size: 514 B

Before After
Before After

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg fill="currentColor" width="100%" height="100%" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g>
<path d="m67.5 12.801c-3.1992-3.1992-8.3984-3.1992-11.602 0l-38.797 38.801c-2.3008 2.3008-2.3008 6.1016 0 8.3984l21.5 21.5c2.3008 2.3008 6.1016 2.3008 8.3984 0l38.801-38.801c3.1992-3.1992 3.1992-8.3984 0-11.602z"/>
<path d="m18.602 88.102h0.19922l10.301-0.30078c3.1016-0.10156 4.6016-3.8984 2.3984-6.1016l-14.699-14.699c-2.1992-2.1992-6-0.69922-6.1016 2.3984l-0.30078 10.301c-0.10156 2.3008 0.80078 4.5 2.3984 6.1016 1.5039 1.5 3.6016 2.3008 5.8047 2.3008z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 645 B

View file

@ -1,6 +0,0 @@
<svg width="100%" height="100%" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<g>
<path d="m82.199 25.301h-64.398c-1.3008 0-2.3008 1.1016-2.1992 2.3984l7.5 62.398c0.5 4.1992 4.1016 7.3984 8.3984 7.3984h37c4.3008 0 7.8984-3.1992 8.3984-7.3984l7.5-62.398c0.10156-1.3008-0.89844-2.3984-2.1992-2.3984zm-45.301 57.699h-0.19922c-1.1992 0-2.1992-0.89844-2.3008-2.1016l-4.1016-38.699c-0.10156-1.3008 0.80078-2.3984 2.1016-2.5 1.3008-0.10156 2.3984 0.80078 2.5 2.1016l4.1016 38.699c0.10156 1.3008-0.80078 2.3984-2.1016 2.5zm15.402-2.3008c0 1.3008-1 2.3008-2.3008 2.3008s-2.3008-1-2.3008-2.3008v-38.699c0-1.3008 1-2.3008 2.3008-2.3008s2.3008 1 2.3008 2.3008zm13.301 0.30078c-0.10156 1.1992-1.1016 2.1016-2.3008 2.1016h-0.19922c-1.3008-0.10156-2.1992-1.3008-2.1016-2.5l4.1016-38.699c0.10156-1.3008 1.3008-2.1992 2.5-2.1016 1.3008 0.10156 2.1992 1.3008 2.1016 2.5z"/>
<path d="m86.602 10.801h-19.301l-4.6016-6.3984c-0.80078-1.1992-2.1992-1.8984-3.6992-1.8984l-18-0.003906c-1.5 0-2.8008 0.69922-3.6992 1.8984l-4.6016 6.3984-19.301 0.003906c-2.3984 0-4.3008 1.8984-4.3008 4.3008 0 2.3984 1.8984 4.3008 4.3008 4.3008h73.199c2.3984 0 4.3008-1.8984 4.3008-4.3008 0-2.4023-1.8984-4.3008-4.2969-4.3008z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -1,8 +0,0 @@
<svg height="100%" width="100%" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1.0666639804840088, 0, 0, 1.0666639804840088, -4.5322370529174805, -4.2468461990356445)">
<path d="m16.086 76.617c0 1.3672 1.1133 2.4805 2.4805 2.4805h49.793c1.3672 0 2.4805-1.1133 2.4805-2.4805v-66.324c0-1.3672-1.1133-2.4805-2.4805-2.4805h-35.352v12.695c0 2.2812-1.8555 4.1328-4.1367 4.1328l-12.785 0.003906zm7.6328-48.016h39.492c0.45703 0 0.82812 0.36719 0.82812 0.82813 0 0.46094-0.36719 0.82812-0.82812 0.82812h-39.492c-0.45703 0-0.82812-0.36719-0.82812-0.82812 0-0.46094 0.37109-0.82813 0.82812-0.82813zm0 10.609h39.492c0.45703 0 0.82812 0.36719 0.82812 0.82812 0 0.46094-0.36719 0.82813-0.82812 0.82813h-39.492c-0.45703 0-0.82812-0.36719-0.82812-0.82813 0-0.45703 0.37109-0.82812 0.82812-0.82812zm0 10.617h39.492c0.45703 0 0.82812 0.36719 0.82812 0.82812s-0.36719 0.82812-0.82812 0.82812h-39.492c-0.45703 0-0.82812-0.36719-0.82812-0.82812s0.37109-0.82812 0.82812-0.82812zm0 10.613h39.492c0.45703 0 0.82812 0.36719 0.82812 0.82812 0 0.46094-0.36719 0.82812-0.82812 0.82812h-39.492c-0.45703 0-0.82812-0.36719-0.82812-0.82812 0-0.46094 0.37109-0.82812 0.82812-0.82812z"/>
<path d="m74.898 14.355h-2.3984v62.258c0 2.2812-1.8555 4.1328-4.1328 4.1328h-45.746v2.4102c0 1.3672 1.1133 2.4805 2.4805 2.4805h49.793c1.3672 0 2.4805-1.1133 2.4805-2.4805l0.003906-66.32c0-1.3633-1.1133-2.4805-2.4805-2.4805z"/>
<path d="m31.352 20.508v-11.531l-14.09 14.016h11.609c1.3711 0 2.4805-1.1172 2.4805-2.4844z"/>
<path d="m29.16 87.297v2.4102c0 1.3672 1.1133 2.4805 2.4805 2.4805h49.793c1.3672 0 2.4805-1.1133 2.4805-2.4805v-66.324c0-1.3672-1.1133-2.4805-2.4805-2.4805h-2.3984v62.258c0 2.2812-1.8555 4.1328-4.1328 4.1328h-45.742z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -1,11 +1,15 @@
Disclaimer:
All icons included in this repo have been scaled and optimized as needed.
Amer Alamer
caret-right.svg (https://thenounproject.com/icon/arrow-caret-right-1143917/)
ui/caret/right.svg (https://thenounproject.com/icon/arrow-caret-right-1143917/)
ui/caret/down.svg (https://thenounproject.com/icon/arrow-caret-down-1143911/)
Alice Design:
garbage-bin.svg (https://thenounproject.com/icon/garbage-2025492/)
ui/garbage-bin.svg (https://thenounproject.com/icon/garbage-2025492/)
zapesicon:
chat-bubble.svg (https://thenounproject.com/icon/chat-6423186/)
ui/chat-bubble.svg (https://thenounproject.com/icon/chat-6423186/)
Fritz Duggan:
dice/d4.svg (https://thenounproject.com/icon/d4-4570604/)
@ -16,18 +20,19 @@ Fritz Duggan:
dice/d20.svg (https://thenounproject.com/icon/d20-4570607/)
Landan Lloyd:
create.svg (https://thenounproject.com/icon/create-1447560/)
ui/plus.svg (https://thenounproject.com/icon/create-1447560/)
Bismillah
ui/minus.svg (https://thenounproject.com/icon/minus-1727966/)
Rokhman Kharis:
close.svg (https://thenounproject.com/icon/close-4996834/)
ui/close.svg (https://thenounproject.com/icon/close-4996834/)
Athok:
sheet.svg (https://thenounproject.com/icon/sheet-5939348/)
ui/sheet.svg (https://thenounproject.com/icon/sheet-5939348/)
Icon Depot:
edit.svg (https://thenounproject.com/icon/edit-1489252/)
ui/pencil.svg (https://thenounproject.com/icon/edit-1489252/)
Oliver Akins:
chat-bubble.svg : Scaling
create.svg : Scaling, Optimization
sheet.svg : Scaling
Muhammad Ahsanu Nadia:
ui/help.svg (https://thenounproject.com/icon/help-6778522/)

1
assets/ui/caret/down.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 100 100"><path d="M50.016 82.137a9.195 9.195 0 0 1-6.844-3.066L2.692 34.91a10.286 10.286 0 0 1-2.691-6.97c0-1.472.304-2.929.898-4.276a9.404 9.404 0 0 1 8.637-5.801h80.93a9.404 9.404 0 0 1 8.637 5.8A10.424 10.424 0 0 1 97.31 34.91L56.853 79.082a9.201 9.201 0 0 1-6.836 3.055z"/></svg>

After

Width:  |  Height:  |  Size: 356 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 100 100"><path d="M82.137 50.016a9.203 9.203 0 0 1-3.066 6.848L34.91 97.309a10.306 10.306 0 0 1-6.97 2.726c-1.472 0-2.929-.308-4.276-.902a9.396 9.396 0 0 1-5.801-8.668V9.535a9.404 9.404 0 0 1 5.8-8.637A10.424 10.424 0 0 1 34.91 2.691l44.172 40.457a9.198 9.198 0 0 1 3.055 6.867z"/></svg>

After

Width:  |  Height:  |  Size: 360 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 100 100"><path d="M61.24 9H42.776C21.393 9 4.095 26.336 4.095 47.679 2.013 74.103 34.856 91.236 48.486 97.153c2.75 1.209 5.792-.834 5.792-3.834v-8.544a4.181 4.181 0 0 1 4.169-4.169h2.75C80.995 80.606 97 64.561 97 44.804 97 25.046 80.954 9 61.197 9h.043ZM32.854 54.389a5.496 5.496 0 0 1-5.5-5.501c0-3.044 2.459-5.5 5.5-5.5a5.495 5.495 0 0 1 5.504 5.5 5.497 5.497 0 0 1-5.504 5.501Zm17.673 0a5.498 5.498 0 0 1-5.502-5.501c0-3.044 2.461-5.5 5.502-5.5a5.494 5.494 0 0 1 5.503 5.5 5.496 5.496 0 0 1-5.503 5.501Zm17.675 0a5.498 5.498 0 0 1-5.505-5.501c0-3.044 2.461-5.5 5.505-5.5a5.495 5.495 0 0 1 5.501 5.5 5.497 5.497 0 0 1-5.501 5.501Z"/></svg>

After

Width:  |  Height:  |  Size: 714 B

1
assets/ui/close.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M96.293 83.457a9.08 9.08 0 0 1 0 12.836 9.08 9.08 0 0 1-12.836 0L51.465 64.301a2.065 2.065 0 0 0-2.93 0L16.543 96.293a9.08 9.08 0 0 1-12.836 0 9.08 9.08 0 0 1 0-12.836L35.7 51.469a2.07 2.07 0 0 0 0-2.934L3.707 16.543a9.08 9.08 0 0 1 0-12.836 9.08 9.08 0 0 1 12.836 0l31.992 31.996a2.072 2.072 0 0 0 2.93 0L83.457 3.707a9.08 9.08 0 0 1 12.836 0 9.08 9.08 0 0 1 0 12.836L64.301 48.535a2.07 2.07 0 0 0 0 2.934z"/></svg>

After

Width:  |  Height:  |  Size: 487 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 100 100"><path d="M82.199 25.301H17.801c-1.3 0-2.3 1.102-2.2 2.398l7.5 62.398c.5 4.2 4.102 7.399 8.4 7.399h37c4.3 0 7.898-3.2 8.398-7.399l7.5-62.398a2.204 2.204 0 0 0-2.2-2.398zM36.898 83h-.2c-1.198 0-2.198-.898-2.3-2.102L30.296 42.2c-.101-1.3.801-2.398 2.102-2.5 1.3-.101 2.398.801 2.5 2.102L39 80.5c.101 1.3-.801 2.398-2.102 2.5zM52.3 80.7c0 1.3-1 2.3-2.3 2.3s-2.302-1-2.302-2.3V42c0-1.3 1-2.3 2.301-2.3s2.301 1 2.301 2.3zm13.301.3a2.296 2.296 0 0 1-2.3 2.102h-.2c-1.3-.102-2.2-1.301-2.102-2.5l4.102-38.7c.102-1.3 1.3-2.199 2.5-2.101 1.3.102 2.2 1.3 2.102 2.5zM86.602 10.801H67.301l-4.602-6.398C61.9 3.203 60.5 2.504 59 2.504L41 2.5c-1.5 0-2.8.7-3.699 1.899l-4.602 6.398-19.3.004a4.269 4.269 0 0 0-4.301 4.3c0 2.4 1.898 4.302 4.3 4.302h73.2c2.398 0 4.3-1.899 4.3-4.301S89 10.8 86.601 10.8z"/></svg>

After

Width:  |  Height:  |  Size: 873 B

1
assets/ui/help.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M50 9.375a40.635 40.635 0 0 0-28.727 11.898 40.63 40.63 0 0 0 0 57.454 40.63 40.63 0 0 0 57.454 0A40.63 40.63 0 0 0 90.625 50a40.658 40.658 0 0 0-11.914-28.711A40.66 40.66 0 0 0 50 9.375zm0 75a34.39 34.39 0 0 1-24.309-10.066 34.386 34.386 0 0 1 0-48.618 34.386 34.386 0 0 1 48.618 0A34.386 34.386 0 0 1 84.375 50a34.407 34.407 0 0 1-10.082 24.293A34.41 34.41 0 0 1 50 84.375z"/><path d="M50 25a15.641 15.641 0 0 0-15.625 15.625v3.125a3.124 3.124 0 1 0 6.25 0v-3.125c0-5.176 4.2-9.375 9.375-9.375s9.375 4.2 9.375 9.375v.457a6.217 6.217 0 0 1-3.438 5.59l-2.136 1.066a12.432 12.432 0 0 0-6.926 11.18v6.707a3.124 3.124 0 1 0 6.25 0v-6.707a6.223 6.223 0 0 1 3.453-5.59l2.137-1.066a12.434 12.434 0 0 0 6.91-11.18v-.457A15.641 15.641 0 0 0 50 25zM53.125 75c0 4.168-6.25 4.168-6.25 0s6.25-4.168 6.25 0"/></svg>

After

Width:  |  Height:  |  Size: 873 B

1
assets/ui/minus.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 100 100"><path fill-rule="evenodd" d="M12.633 38.727h74.734c6.258 0 11.336 6.227 11.336 11.273 0 6.227-5.074 11.273-11.336 11.273H12.633C6.375 61.273 1.297 55.046 1.297 50c0-6.227 5.074-11.273 11.336-11.273z"/></svg>

After

Width:  |  Height:  |  Size: 289 B

1
assets/ui/pencil.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 100 100"><path d="M67.5 12.801c-3.2-3.2-8.398-3.2-11.602 0L17.101 51.602c-2.3 2.3-2.3 6.102 0 8.398l21.5 21.5c2.3 2.301 6.102 2.301 8.398 0L85.8 42.7c3.2-3.2 3.2-8.399 0-11.603zM18.602 88.102h.2l10.3-.3c3.102-.102 4.602-3.9 2.399-6.102L16.8 67c-2.199-2.199-6-.699-6.101 2.399L10.4 79.7c-.102 2.3.8 4.5 2.398 6.102 1.504 1.5 3.601 2.3 5.804 2.3z"/></svg>

After

Width:  |  Height:  |  Size: 426 B

View file

Before

Width:  |  Height:  |  Size: 536 B

After

Width:  |  Height:  |  Size: 536 B

Before After
Before After

1
assets/ui/sheet.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M12.626 77.478a2.65 2.65 0 0 0 2.646 2.646h53.112a2.65 2.65 0 0 0 2.646-2.646V6.732a2.65 2.65 0 0 0-2.646-2.646H30.676v13.542a4.414 4.414 0 0 1-4.413 4.408l-13.637.004zm8.142-51.217h42.124c.488 0 .884.391.884.883a.878.878 0 0 1-.884.883H20.768a.881.881 0 0 1-.884-.883c0-.492.396-.883.884-.883zm0 11.316h42.124c.488 0 .884.392.884.883a.878.878 0 0 1-.884.884H20.768a.884.884 0 0 1 0-1.767zm0 11.325h42.124c.488 0 .884.391.884.883s-.392.883-.884.883H20.768c-.488 0-.884-.391-.884-.883s.396-.883.884-.883zm0 11.32h42.124c.488 0 .884.392.884.884a.878.878 0 0 1-.884.883H20.768a.881.881 0 0 1-.884-.883c0-.492.396-.884.884-.884z"/><path d="M75.359 11.065H72.8v66.408a4.413 4.413 0 0 1-4.408 4.409H19.597v2.57a2.65 2.65 0 0 0 2.645 2.647h53.113A2.65 2.65 0 0 0 78 84.453l.004-70.741a2.652 2.652 0 0 0-2.646-2.646zM28.91 17.628v-12.3L13.88 20.28h12.383a2.65 2.65 0 0 0 2.646-2.65z"/><path d="M26.572 88.87v2.57a2.65 2.65 0 0 0 2.646 2.646H82.33a2.65 2.65 0 0 0 2.646-2.645V20.695a2.65 2.65 0 0 0-2.646-2.646h-2.558v66.409a4.413 4.413 0 0 1-4.409 4.408H26.572z"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

9
augments.d.ts vendored Normal file
View file

@ -0,0 +1,9 @@
interface Actor {
/** The system-specific data */
system: any;
};
interface Item {
/** The system-specific data */
system: any;
};

7
jsconfig.json Normal file
View file

@ -0,0 +1,7 @@
{
"compilerOptions": {
"types": [
"./augments.d.ts"
]
}
}

129
langs/en-ca.2.json Normal file
View file

@ -0,0 +1,129 @@
{
"dotdungeon": {
"stat": {
"build": "Build",
"meta": "Meta",
"presence": "Presence",
"hands": "Hands",
"tilt": "Tilt",
"rng": "RNG"
},
"skills": {
"defense": "Defense",
"magic": "Magic",
"melee": "Melee",
"platforming": "Platforming",
"strength": "Strength",
"alchemy": "Alchemy",
"arcanum": "Arcanum",
"dreams": "Dreams",
"lore": "Lore",
"navigation": "Navigation",
"animal_handling": "Animal Handling",
"perception": "Perception",
"sneak": "Sneak",
"speech": "Speech",
"vibes": "Vibes",
"accuracy": "Accuracy",
"crafting": "Crafting",
"engineering": "Engineering",
"explosives": "Explosives",
"piloting": "Piloting"
},
"trainingLevel": {
"untrained": "Untrained",
"trained": "Trained",
"expert": "Expert",
"locked": "Locked"
},
"die": {
"d4": "d4",
"d6": "d6",
"d8": "d8",
"d10": "d10",
"d12": "d12",
"d20": "d20"
},
"sheet": {
"actor": {
"v2": {
"stat-not-chosen": "Select a dice to see the {name} skills",
"skill-roll-locked": "@dotdungeon.trainingLevel.locked",
"toggle-item-information": "Toggle the item's extra information visibility",
"create-item": "Create @TYPES.Item.{type}"
}
},
"item": {
"untyped": {
"quantity": "Quantity",
"usage": "Usage Cost",
"rarity": "Tier",
"no-description": "This item hasn't been described yet..."
}
}
},
"rarity": {
"simple": "Simple",
"greater": "Greater",
"rare": "Rare",
"legendary": "Legendary"
},
"location": {
"unknown": "@dotdungeon.common.empty",
"inventory": "Inventory",
"equipped": "Equipped",
"storage": "Storage"
},
"default": {
"name": "(Unnamed @TYPES.{document}.{type})"
},
"common": {
"send-to-chat": "Send to Chat",
"edit": "Edit",
"delete": "Delete",
"reset": "Reset",
"empty": "---",
"help": "Help",
"gm": "Server",
"view-larger": "View Larger"
},
"sheet-names": {
"*DataSheet": "Data Sheet"
},
"help-tooltips": {
"calculated-capacity": {
"title": "What is Calculated Capacity?",
"content": "<p>The calculated capacity is how much space in your inventory that the item will take up, the way it is calculated is determined by the item. Usually the main thing that affects the capacity is the item's quantity, but this can be turned off by the @dotdungeon.common.gm, which means that no matter the quantity it will only use up one capacity. The @dotdungeon.common.gm can also entirely disable capacity usage which will make the used capacity always be zero.</p>"
}
},
"delete": {
"ActiveEffect": {
"title": "Delete Effect",
"content": "<p>Are you sure you would like to delete the active effect: {name}</p>"
}
}
},
"TYPES": {
"Actor": {
"player": "Player",
"sync": "Sync"
},
"Item": {
"aspect": "Aspect",
"weapon": "Weapon",
"armour": "Armour",
"equipment": "Equipment",
"foil": "Foil",
"pet": "Pet",
"structure": "Structure",
"service": "Service",
"material": "Materials",
"legendaryItem": "Legendary Item",
"spell": "Spell",
"untyped": "Custom"
},
"ActiveEffect": {
"base": "Effect"
}
}
}

View file

@ -78,13 +78,17 @@
}
},
"sheet-names": {
"PlayerSheet": "PC/PUG Sheet",
"PlayerSheet": {
"MVP": "MVP PC Sheet",
"v2": "PC Sheet"
},
"SyncSheet": {
"basic": "Theme: Basic"
},
"AspectSheet": "Aspect Sheet",
"SpellSheet": "Spell Sheet",
"PetSheet": "Pet Sheet"
"PetSheet": "Pet Sheet",
"UntypedItemSheet": "Custom Item"
},
"actor": {
"pc": {
@ -253,6 +257,9 @@
},
"warn": {
"negative-aspect-limit": "The Aspect limit must be 0 or greater"
},
"info": {
"increased-item-quantity": "Increased the item quantity for: {name}"
}
},
"dialogs": {
@ -273,6 +280,12 @@
"title": "You want to kill your pet?!",
"content": "Are you sure you would like to kill the pet: {name}<br /><br />This action cannot be undone."
}
},
"untyped": {
"delete": {
"title": "Confirm Item Deletion",
"content": "Are you sure you would like to delete the item: {name}<br /><br />This action cannot be undone."
}
}
},
"keyword": {
@ -316,6 +329,9 @@
},
"pet": {
"name": "(Unnamed Pet)"
},
"untyped": {
"name": "Unknown Item"
}
}
},

125
module/components/icon.mjs Normal file
View file

@ -0,0 +1,125 @@
import { StyledShadowElement } from "./mixins/Styles.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 DotDungeonIcon extends StyledShadowElement(HTMLElement) {
static elementName = `dd-icon`;
static formAssociated = false;
/* Stuff for the mixin to use */
static _stylePath = `v3/components/icon.css`;
static _cache = new Map();
#container;
/** @type {null | string} */
_name;
/** @type {null | string} */
_path;
/* Stored IDs for all of the hooks that are in this component */
#svgHmr;
constructor() {
super();
// this._shadow = this.attachShadow({ mode: `open`, delegatesFocus: true });
this.#container = document.createElement(`div`);
this._shadow.appendChild(this.#container);
};
_mounted = false;
async connectedCallback() {
super.connectedCallback();
if (this._mounted) return;
this._name = this.getAttribute(`name`);
this._path = this.getAttribute(`path`);
/*
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);
};
};
/*
Try to retrieve the icon if it isn't present, try the path then default to
the slot content, as then we can have a default per-icon usage
*/
let content;
if (this._name) {
content = await this.#getIcon(`./systems/dotdungeon/assets/${this._name}.svg`);
};
if (this._path && !content) {
content = await this.#getIcon(this._path);
};
if (content) {
this.#container.appendChild(content.cloneNode(true));
};
/*
This is so that when we get an HMR event from Foundry we can appropriately
handle it using our logic to update the component and the icon cache.
*/
if (game.settings.get(`dotdungeon`, `devMode`)) {
this.#svgHmr = Hooks.on(`dd-hmr:svg`, (iconName, data) => {
if (this._name === iconName || this._path?.endsWith(data.path)) {
const svg = this.#parseSVG(data.content);
this.constructor._cache.set(iconName, svg);
this.#container.replaceChildren(svg.cloneNode(true));
};
});
};
this._mounted = true;
};
disconnectedCallback() {
super.disconnectedCallback();
if (!this._mounted) return;
Hooks.off(`dd-hmr:svg`, this.#svgHmr);
this._mounted = false;
};
async #getIcon(path) {
// Cache hit!
if (this.constructor._cache.has(path)) {
console.debug(`.dungeon | Icon ${path} cache hit`);
return this.constructor._cache.get(path);
};
const r = await fetch(path);
switch (r.status) {
case 200:
case 201:
break;
default:
console.error(`.dungeon | Failed to fetch icon: ${path}`);
return;
};
console.debug(`.dungeon | Adding icon ${path} to the cache`);
const svg = this.#parseSVG(await r.text());
this.constructor._cache.set(path, svg);
return svg;
};
/** Takes an SVG string and returns it as a DOM node */
#parseSVG(content) {
const temp = document.createElement(`div`);
temp.innerHTML = content;
return temp.querySelector(`svg`);
};
};

View file

@ -0,0 +1,149 @@
import { DotDungeonIcon } from "./icon.mjs";
import { StyledShadowElement } from "./mixins/Styles.mjs";
/**
Attributes:
@property {string} name - The path to the value to update
@property {number} value - The actual value of the input
@property {number} min - The minimum value of the input
@property {number} max - The maximum value of the input
@property {number?} smallStep - The step size used for the buttons and arrow keys
@property {number?} largeStep - The step size used for the buttons + Ctrl and page up / down
Styling:
- `--height`: Controls the height of the element + the width of the buttons (default: 1.25rem)
- `--width`: Controls the width of the number input (default 50px)
*/
export class DotDungeonIncrementer extends StyledShadowElement(HTMLElement) {
static elementName = `dd-incrementer`;
static formAssociated = true;
static _stylePath = `v3/components/incrementer.css`;
_internals;
#input;
_min;
_max;
_smallStep;
_largeStep;
constructor() {
super();
// Form internals
this._internals = this.attachInternals();
this._internals.role = `spinbutton`;
};
get form() {
return this._internals.form;
}
get name() {
return this.getAttribute(`name`);
}
set name(value) {
this.setAttribute(`name`, value);
}
get value() {
return this.getAttribute(`value`);
};
set value(value) {
this.setAttribute(`value`, value);
};
get type() {
return `number`;
}
connectedCallback() {
super.connectedCallback();
this.replaceChildren();
// Attribute parsing / registration
const value = this.getAttribute(`value`);
this._min = parseInt(this.getAttribute(`min`) ?? 0);
this._max = parseInt(this.getAttribute(`max`) ?? 0);
this._smallStep = parseInt(this.getAttribute(`smallStep`) ?? 1);
this._largeStep = parseInt(this.getAttribute(`largeStep`) ?? 5);
this._internals.ariaValueMin = this._min;
this._internals.ariaValueMax = this._max;
const container = document.createElement(`div`);
// The input that the user can see / modify
const input = document.createElement(`input`);
this.#input = input;
input.type = `number`;
input.ariaHidden = true;
input.min = this.getAttribute(`min`);
input.max = this.getAttribute(`max`);
input.addEventListener(`change`, this.#updateValue.bind(this));
input.value = value;
// plus button
const increment = document.createElement(DotDungeonIcon.elementName);
increment.setAttribute(`name`, `ui/plus`);
increment.setAttribute(`var:size`, `0.75rem`);
increment.setAttribute(`var:fill`, `currentColor`);
increment.ariaHidden = true;
increment.classList.value = `increment`;
increment.addEventListener(`mousedown`, this.#increment.bind(this));
// minus button
const decrement = document.createElement(DotDungeonIcon.elementName);
decrement.setAttribute(`name`, `ui/minus`);
decrement.setAttribute(`var:size`, `0.75rem`);
decrement.setAttribute(`var:fill`, `currentColor`);
decrement.ariaHidden = true;
decrement.classList.value = `decrement`;
decrement.addEventListener(`mousedown`, this.#decrement.bind(this));
// Construct the DOM
container.appendChild(decrement);
container.appendChild(input);
container.appendChild(increment);
this._shadow.appendChild(container);
/*
This converts all of the namespace 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);
};
};
};
#updateValue() {
let value = parseInt(this.#input.value);
if (this.getAttribute(`min`)) value = Math.max(this._min, value);
if (this.getAttribute(`max`)) value = Math.min(this._max, value);
this.#input.value = value;
this.value = value;
this.dispatchEvent(new Event(`change`, { bubbles: true }));
};
/** @param {Event} $e */
#increment($e) {
$e.preventDefault();
let value = parseInt(this.#input.value);
value += $e.ctrlKey ? this._largeStep : this._smallStep;
this.#input.value = value;
this.#updateValue();
};
/** @param {Event} $e */
#decrement($e) {
$e.preventDefault();
let value = parseInt(this.#input.value);
value -= $e.ctrlKey ? this._largeStep : this._smallStep;
this.#input.value = value;
this.#updateValue();
};
};

View file

@ -0,0 +1,23 @@
import { DotDungeonIncrementer } from "./incrementer.mjs";
import { DotDungeonIcon } from "./icon.mjs";
const components = [
DotDungeonIcon,
DotDungeonIncrementer,
];
export function registerCustomComponents() {
(CONFIG.CACHE ??= {}).componentListeners ??= [];
for (const component of components) {
if (!window.customElements.get(component.elementName)) {
console.debug(`.dungeon | Registering component "${component.elementName}"`);
window.customElements.define(
component.elementName,
component
);
if (component.formAssociated) {
CONFIG.CACHE.componentListeners.push(component.elementName);
}
};
}
};

View file

@ -0,0 +1,80 @@
/**
* @param {HTMLElement} Base
*/
export function StyledShadowElement(Base) {
return class extends Base {
/**
* The path to the CSS that is loaded
* @type {string}
*/
static _stylePath;
/**
* The stringified CSS to use
* @type {string}
*/
static _styles;
/**
* The HTML element of the stylesheet
* @type {HTMLStyleElement}
*/
_style;
/** @type {ShadowRoot} */
_shadow;
/**
* The hook ID for this element's CSS hot reload
* @type {number}
*/
#cssHmr;
constructor() {
super();
this._shadow = this.attachShadow({ mode: `open` });
this._style = document.createElement(`style`);
this._shadow.appendChild(this._style);
};
#mounted = false;
connectedCallback() {
if (this.#mounted) return;
this._getStyles();
if (game.settings.get(`dotdungeon`, `devMode`)) {
this.#cssHmr = Hooks.on(`dd-hmr:css`, (data) => {
if (data.path.endsWith(this.constructor._stylePath)) {
this._style.innerHTML = data.content;
};
});
};
this.#mounted = true;
};
disconnectedCallback() {
if (!this.#mounted) return;
if (this.#cssHmr != null) {
Hooks.off(`dd-hmr:css`, this.#cssHmr);
this.#cssHmr = null;
};
this.#mounted = false;
};
_getStyles() {
if (this.constructor._styles) {
this._style.innerHTML = this.constructor._styles;
} else {
fetch(`./systems/dotdungeon/.styles/${this.constructor._stylePath}`)
.then(r => r.text())
.then(t => {
this.constructor._styles = t;
this._style.innerHTML = t;
});
}
};
};
};

View file

@ -1,35 +1,71 @@
const statDice = [ `d4`, `d6`, `d8`, `d10`, `d12`, `d20` ];
export const statDice = [ `d4`, `d6`, `d8`, `d10`, `d12`, `d20` ];
const trainingLevels = [``, `locked`, `+2`, `+4`];
export const trainingLevels = [
{ key: "locked", label: "dotdungeon.trainingLevel.locked", value: -1 },
{ key: "untrained", label: "dotdungeon.trainingLevel.untrained", value: 0 },
{ key: "trained", label: "dotdungeon.trainingLevel.trained", value: 2 },
{ key: "expert", label: "dotdungeon.trainingLevel.expert", value: 4 },
];
const damageTypes = [ `slashing`, `piercing`, `smashing`, `gun`, `neon`, `shadow`, `solar` ];
export const damageTypes = [ `slashing`, `piercing`, `smashing`, `gun`, `neon`, `shadow`, `solar` ];
const ammoTypes = [`quivers`, `mags`, `cells`];
export const ammoTypes = [`quivers`, `mags`, `cells`];
const stats = [ `build`, `meta`, `presence`, `hands`, `tilt`, `rng` ];
export const stats = [ `build`, `meta`, `presence`, `hands`, `tilt`, `rng` ];
const buildSkills = [ `defense`, `magic`, `melee`, `platforming`, `strength`, ];
const metaSkills = [ `alchemy`, `arcanum`, `dreams`, `lore`, `navigation`, ];
const presenceSkills = [ `animal_handling`, `perception`, `sneak`, `speech`, `vibes`, ];
const handsSkills = [ `accuracy`, `crafting`, `engineering`, `explosives`, `piloting`, ];
export const buildSkills = [ `defense`, `magic`, `melee`, `platforming`, `strength`, ];
export const metaSkills = [ `alchemy`, `arcanum`, `dreams`, `lore`, `navigation`, ];
export const presenceSkills = [ `animal_handling`, `perception`, `sneak`, `speech`, `vibes`, ];
export const handsSkills = [ `accuracy`, `crafting`, `engineering`, `explosives`, `piloting`, ];
const allSkills = [
export const allSkills = [
...buildSkills,
...metaSkills,
...presenceSkills,
...handsSkills,
];
const skills = {
export const skills = {
build: buildSkills,
meta: metaSkills,
presence: presenceSkills,
hands: handsSkills,
};
const itemTiers = [
`simple`, `greater`,
`rare`, `legendary`
export const defaultItemTier = `simple`;
export const itemTiers = [
{ value: `simple`, label: `dotdungeon.rarity.simple` },
{ value: `greater`, label: `dotdungeon.rarity.greater` },
{ value: `rare`, label: `dotdungeon.rarity.rare` },
{ value: `legendary`, label: `dotdungeon.rarity.legendary` },
];
export const syncMilestones = [
{ value: 20, andReturn: true },
{ value: 40, andReturn: false },
{ value: 60, andReturn: true },
{ value: 80, andReturn: false },
{ value: 100, andReturn: true },
];
export const syncDice = `1d20`;
export const localizerConfig = {
subKeyPattern: /@(?<key>[a-zA-Z\.]+)/gm,
maxDepth: 10,
};
export const itemFilters = [
`material`,
`untyped`,
`aspect`,
`weapon`,
`armour`,
`equipment`,
`foil`,
`pet`,
`structure`,
`service`,
];
export default {
@ -44,5 +80,10 @@ export default {
handsSkills,
allSkills,
skills,
defaultItemTier,
itemTiers,
syncMilestones,
syncDice,
localizerConfig,
itemFilters,
};

View file

@ -0,0 +1,82 @@
import { GenericDialog } from "./GenericDialog.mjs";
export class DiceList extends GenericDialog {
constructor(mobActor) {
super({}, { title: `${mobActor.name}'s Dice List` });
this.actor = mobActor;
this.dice = this.actor.system.dice.map((d) => ({
...d,
id: randomID(),
}));
};
static get defaultOptions() {
const opts = foundry.utils.mergeObject({
...super.defaultOptions,
template: `systems/dotdungeon/templates/dialogs/diceList.hbs`,
width: 275,
height: 400,
submitOnClose: false,
resizable: true,
});
opts.classes?.push(`dotdungeon`);
return opts;
};
async getData() {
const ctx = await super.getData();
ctx.dice = this.dice;
return ctx;
};
async activateListeners(html) {
super.activateListeners(html);
if (!this.isEditable) return;
console.debug(`.dungeon | DiceList adding event listeners`);
html.find(`[data-die-update]`)
.on(`change`, this.updateDieInMemoryOnly.bind(this))
};
async _updateObject(_event, formData) {
const newDice = this.dice.map(d => {
return {
count: formData[`${d.id}.count`],
sides: formData[`${d.id}.sides`],
repeat: formData[`${d.id}.repeat`],
};
});
await this.actor.update({ "system.dice": newDice });
};
updateDieInMemoryOnly($e) {
const target = $e.currentTarget;
const data = target.dataset;
const value = target.value;
const [ dieId, field ] = data.dieUpdate.split(`.`);
for (const die of this.dice) {
if (die.id === dieId) {
die[field] = value;
return
};
};
};
addDie() {
this.dice.push({
count: 1,
sides: 2,
repeat: 1,
id: randomID(),
});
this.render();
};
deleteDie($e) {
const data = $e.currentTarget.dataset;
this.dice = this.dice.filter(d => d.id !== data.id);
this.render();
};
};

View file

@ -1,23 +1,11 @@
import DOTDUNGEON from "../config.mjs";
import { preloadIcons } from "../handlebars.mjs";
export class GenericItemSheet extends ItemSheet {
_expanded = new Set();
export class GenericDialog extends FormApplication {
#propogatedSettings = [
`devMode`,
`showAvatarOnSheet`,
`playersCanChangeGroup`,
`resourcesOrSupplies`,
];
activateListeners(html) {
super.activateListeners(html);
if (!this.isEditable) return;
console.debug(`.dungeon | Adding event listeners for Generic Item: ${this.id}`);
};
async getData() {
const ctx = {};
@ -31,12 +19,31 @@ export class GenericItemSheet extends ItemSheet {
ctx.meta = {
expanded: this._expanded,
idp: this.item.uuid,
};
ctx.config = DOTDUNGEON;
ctx.icons = await preloadIcons();
ctx.icons = CONFIG.CACHE.icons;
return ctx;
};
activateListeners(html) {
super.activateListeners(html);
if (!this.isEditable) return;
console.debug(`.dungeon | Generic dialog adding listeners`);
html.find(`[data-action]`)
.on(`click`, this._handleActionClick.bind(this));
};
_handleActionClick($e) {
const data = $e.currentTarget.dataset;
if (!this[data.action]) return;
this[data.action].bind(this)($e);
};
closeNoSave() {
this.close({ submit: false, });
};
};

View file

@ -1,27 +0,0 @@
const diceOptions = [
`d4`,
`d6`,
`d8`,
`d10`,
`d12`,
`d20`
]
export default Dialog({
title: `Die Selector`,
content: `<p>Select a Dice</p>`,
buttons: {
d4: {
label: "d4",
callback() {
console.log(`Selected a d4`)
}
},
d6: {
label: "d6",
callback() {
console.log(`Selected a d6`)
}
}
}
})

View file

@ -0,0 +1,7 @@
export class DotDungeonActiveEffect extends ActiveEffect {
// Invert the logic of the disabled property so it's easier to modify via
// embedded controls
get enabled() { return !this.disabled };
set enabled(newValue) { this.disabled = !newValue };
};

View file

@ -0,0 +1,42 @@
import { DotDungeonActiveEffect } from "./GenericActiveEffect.mjs";
const classes = {};
const defaultClass = DotDungeonActiveEffect;
export const ActiveEffectProxy = new Proxy(function () {}, {
construct(target, args) {
const [data] = args;
if (!classes.hasOwnProperty(data.type)) {
return new defaultClass(...args);
}
return new classes[data.type](...args);
},
get(target, prop, receiver) {
if (["create", "createDocuments"].includes(prop)) {
return function (data, options) {
if (data.constructor === Array) {
return data.map(i => ActiveEffectProxy.create(i, options))
}
if (!classes.hasOwnProperty(data.type)) {
return defaultClass.create(data, options);
}
return classes[data.type].create(data, options);
};
};
if (prop == Symbol.hasInstance) {
return function (instance) {
if (instance instanceof defaultClass) return true;
return Object.values(classes).some(i => instance instanceof i);
};
};
return defaultClass[prop];
},
});

View file

@ -0,0 +1,49 @@
export class DotDungeonActor extends Actor {
/*
Using this to take a "snapshot" of the system data prior to applying AE's so
that the inputs can still have the non-modified value in them, while we still
provide all that data to AE's without needing to disable any inputs.
*/
prepareEmbeddedDocuments() {
this.preAE = foundry.utils.deepClone(this.system);
super.prepareEmbeddedDocuments();
};
async createEmbeddedItem(defaults, opts = {}) {
let items = await this.createEmbeddedDocuments(`Item`, defaults);
if (!Array.isArray(items)) items = items ? [items] : [];
if (items.length == 0) {
throw new Error(`Failed to create any items`);
};
this.sheet.render();
if (
game.settings.get(`dotdungeon`, `openEmbeddedOnCreate`)
&& !opts.overrideSheetOpen
) {
for (const item of items) {
item.sheet.render(true);
};
};
};
async preItemEmbed(item) {
// Increases the quantity of already present items if they match via source
let embedded = this.itemTypes[item.type].find(i => {
return i.getFlag(`core`, `sourceId`) === `Item.${item.id}`
});
if (embedded) {
await embedded.update({"system.quantity": embedded.system.quantity + 1});
ui.notifications.info(
game.i18n.format(
`dotdungeon.notification.info.increased-item-quantity`,
{ name: embedded.name, quantity: embedded.system.quantity }
),
{ console: false }
);
return false;
};
return true;
};
};

View file

@ -1,92 +0,0 @@
import PlayerActor from "./Player.mjs";
import MobActor from "./Mob.mjs";
/** @extends {Actor} */
export class ActorHandler extends Actor {
proxyTargets = {
player: PlayerActor,
mob: MobActor,
};
constructor(data, ctx) {
super(data, ctx);
};
/** @type {class|undefined} */
get fn() {
return this.proxyTargets[this.type];
};
async proxyFunction(funcName, ...args) {
if (!this.fn?.[funcName]) return;
return await this.fn?.[funcName].bind(this)(...args);
};
async openEmbeddedSheet($event) {
if (this.fn?.openEmbeddedSheet) {
this.fn.openEmbeddedSheet.bind(this)($event);
} else {
const data = $event.target.dataset;
let item = await fromUuid(data.embeddedEdit);
item?.sheet.render(true);
};
};
async genericEmbeddedUpdate($event) {
if (this.fn?.genericEmbeddedUpdate) {
return this.fn.genericEmbeddedUpdate.bind(this)($event);
};
const target = $event.delegateTarget;
const data = target.dataset;
const item = await fromUuid(data.embeddedId);
let value = target.value;
switch (target.type) {
case "checkbox": value = target.checked; break;
};
await item?.update({ [data.embeddedUpdate]: value });
};
async genericEmbeddedDelete($event) {
if (!this.fn?.genericEmbeddedDelete) return;
this.fn.genericEmbeddedDelete.bind(this)($event);
};
async genericEmbeddedCreate($event) {
const data = $event.currentTarget.dataset;
if (!this.fn?.[`createCustom${data.embeddedCreate}`]) return;
this.fn?.[`createCustom${data.embeddedCreate}`].bind(this)($event);
};
async genericSendToChat($event) {
const data = $event.currentTarget.dataset;
const type = data.messageType;
console.log(data)
if (this.fn?.[`send${type}ToChat`]) {
return await this.fn?.[`send${type}ToChat`].bind(this)($event);
};
if (!data.messageContent) {
console.warn(`.dungeon | Tried to send a chat message with no content`);
return;
};
let message = await ChatMessage.create({
content: data.messageContent,
flavor: data.messageFlavor,
speaker: { actor: this.actor }
});
message.render();
};
/**
* @param {ItemHandler} item
* @returns {boolean} true to allow the document to be embedded
*/
async preItemEmbed(item) {
let type = item.type[0].toUpperCase() + item.type.slice(1);
if (this.fn?.[`pre${type}Embed`]) {
return await this.fn?.[`pre${type}Embed`].bind(this)(item);
};
return true;
};
};

View file

@ -1 +1,10 @@
export default {};
import { DotDungeonActor } from "./GenericActor.mjs";
export class Mob extends DotDungeonActor {
getRollData() {
const data = {
initiative: this.system.initiative ?? 0,
};
return data;
};
};

View file

@ -1,116 +1,51 @@
import { ItemHandler } from "../Item/Handler.mjs";
import { DotDungeonActor } from "./GenericActor.mjs";
/** @this {Actor} */
async function genericEmbeddedDelete($event) {
let data = $event.currentTarget.dataset;
let item = await fromUuid(data.embeddedId);
export class Player extends DotDungeonActor {
if (!item) {
ui.notifications.error(
`dotdungeon.notification.error.item-not-found`,
{ console: false }
applyActiveEffects() {
super.applyActiveEffects();
/*
These are the (groups of) fields that ActiveEffects may modify safely and
remain editable in the sheet. This needs to be done because of default
Foundry behaviour that otherwise prevents these fields from being edited.
The deletes must use optional chaining otherwise they can cause issues
during the document preparation lifecycle as an actor with no AE's affecting
anything in one of these areas will result in these paths being undefined.
*/
delete this.overrides.system?.stats;
delete this.overrides.system?.skills;
};
async createCustomPet() {
const body = new URLSearchParams({
number: 1,
animal: `Cat`,
"X-Requested-With": "fetch"
});
const r = await fetch(
`https://randommer.io/pet-names`,
{
method: "POST",
body
}
);
return;
await this.createEmbeddedItem([{
type: `pet`,
name: (await r.json())[0] ?? game.i18n.localize(`dotdungeon.defaults.pet.name`),
}]);
};
Dialog.confirm({
title: game.i18n.format(
`dotdungeon.dialogs.${item.type}.delete.title`,
item
),
content: game.i18n.format(
`dotdungeon.dialogs.${item.type}.delete.content`,
item
),
yes: () => {
item.delete();
},
defaultYes: false,
});
};
/** @this {Actor} */
async function createCustomItem(defaults, opts = {}) {
let items = await this.createEmbeddedDocuments(`Item`, defaults);
if (items.length == 0) {
throw new Error();
get atAspectLimit() {
let limit = game.settings.get(`dotdungeon`, `aspectLimit`);
return this.itemTypes.aspect.length >= limit;
};
this.sheet.render();
if (
game.settings.get(`dotdungeon`, `openEmbeddedOnCreate`)
&& !opts.overrideSheetOpen
) {
for (const item of items) {
item.sheet.render(true);
getRollData() {
const data = {
initiative: this.system.stats.hands ?? 0,
stats: this.system.stats,
};
return data;
};
};
/** @this {Actor} */
async function createCustomAspect() {
await createCustomItem.bind(this)([{
type: `aspect`,
name: game.i18n.format(`dotdungeon.defaults.aspect.name`),
}]);
};
/** @this {Actor} */
async function createCustomSpell() {
await createCustomItem.bind(this)([{
type: `spell`,
name: game.i18n.format(`dotdungeon.defaults.spell.name`),
}]);
};
/** @this {Actor} */
async function createCustomPet() {
const body = new URLSearchParams({
number: 1,
animal: `Cat`,
"X-Requested-With": "fetch"
})
const r = await fetch(
`https://randommer.io/pet-names`,
{
method: "POST",
body
}
);
await createCustomItem.bind(this)([{
type: `pet`,
name: (await r.json())[0] ?? game.i18n.localize(`dotdungeon.defaults.pet.name`),
}]);
};
/** @this {Actor} */
async function atAspectLimit() {
let limit = game.settings.get(`dotdungeon`, `aspectLimit`);
return this.itemTypes.aspect.length >= limit;
};
/**
* @param {ItemHandler} item
* @this {Actor}
*/
async function preAspectEmbed(item) {
if (await atAspectLimit.bind(this)()) {
ui.notifications.error(
game.i18n.format(
`dotdungeon.notification.error.aspect-limit-reached`,
{ limit: game.settings.get(`dotdungeon`, `aspectLimit`) }
),
{ console: false }
);
return false;
};
};
export default {
atAspectLimit,
createCustomItem,
createCustomAspect,
createCustomSpell,
createCustomPet,
genericEmbeddedDelete,
preAspectEmbed,
};

View file

@ -0,0 +1,56 @@
import { DotDungeonActor } from "./GenericActor.mjs";
import { syncMilestones } from "../../config.mjs";
export class Sync extends DotDungeonActor {
async useRestDie() {
let addToSync = await (new Roll(syncDice)).evaluate();
await addToSync.toMessage({
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
flavor: `Sync Restoration`,
});
this.update({
"system.rest_dice": this.system.rest_dice - 1,
"system.value": this.system.value + addToSync.total,
});
};
async _preUpdate(data, options) {
if (options.diff) {
if (data.system?.value != null) {
let currentSync = this.system.value;
let newSync = data.system.value;
let minSync = Math.min(currentSync, newSync);
let maxSync = Math.max(currentSync, newSync);
let milestones = syncMilestones.filter(
m => minSync < m.value && m.value <= maxSync
);
if (milestones.length > 0) data.system.rest_dice ??= this.system.rest_dice;
for (const milestone of milestones) {
// Damage
if (newSync < currentSync) {
if (!this.system.milestones_hit.has(milestone.value)) {
data.system.rest_dice += 1;
this.system.milestones_hit.add(milestone.value);
};
}
// Healing
else if (newSync > currentSync) {
if (
this.system.milestones_hit.has(milestone.value)
&& milestone.andReturn
&& milestone.value <= newSync
) {
this.system.milestones_hit.delete(milestone.value);
};
};
};
data.system.milestones_hit = [ ...this.system.milestones_hit ];
};
};
};
};

View file

@ -0,0 +1,49 @@
import { DotDungeonActor } from "./GenericActor.mjs";
import { Player } from "./Player.mjs";
import { Sync } from "./Sync.mjs";
import { Mob } from "./Mob.mjs";
const classes = {
player: Player,
mob: Mob,
sync: Sync,
};
const defaultClass = DotDungeonActor;
export const ActorProxy = new Proxy(function () {}, {
construct(target, args) {
const [data] = args;
if (!classes.hasOwnProperty(data.type)) {
return new defaultClass(...args);
}
return new classes[data.type](...args);
},
get(target, prop, receiver) {
if (["create", "createDocuments"].includes(prop)) {
return function (data, options) {
if (data.constructor === Array) {
return data.map(i => ActorProxy.create(i, options))
}
if (!classes.hasOwnProperty(data.type)) {
return defaultClass.create(data, options);
}
return classes[data.type].create(data, options);
};
};
if (prop == Symbol.hasInstance) {
return function (instance) {
if (instance instanceof defaultClass) return true;
return Object.values(classes).some(i => instance instanceof i);
};
};
return defaultClass[prop];
},
});

View file

@ -1,10 +1,42 @@
/** @this {ItemHandler} */
async function _preCreate(_data, _options, _user) {
if (this.isEmbedded) {
return await this.actor?.preItemEmbed(this);
import { DotDungeonItem } from "./GenericItem.mjs";
const secondsInAMinute = 60;
const secondsInAnHour = 60 * secondsInAMinute;
export class Aspect extends DotDungeonItem {
async _preCreate() {
if (this.isEmbedded) {
if (this.actor.atAspectLimit) {
ui.notifications.error(
game.i18n.format(
`dotdungeon.notification.error.aspect-limit-reached`,
{ limit: game.settings.get(`dotdungeon`, `aspectLimit`) }
),
{ console: false }
);
return false;
};
return await this.actor?.preItemEmbed(this);
};
};
get friendlyDuration() {
let friendly = ``;
let duration = this.system.deactivateAfter;
if (duration >= secondsInAnHour) {
let hours = Math.floor(duration / secondsInAnHour);
friendly += `${hours}h`;
duration -= hours * secondsInAnHour;
};
if (duration >= secondsInAMinute) {
let minutes = Math.floor(duration / secondsInAMinute);
friendly += `${minutes}m`;
duration -= minutes * secondsInAMinute;
};
if (duration > 0) {
friendly += `${duration}s`;
};
return friendly;
};
};
export default {
_preCreate,
};

View file

@ -0,0 +1,24 @@
export class DotDungeonItem extends Item {
async _preCreate() {
if (this.isEmbedded) {
return await this.actor?.preItemEmbed(this);
};
};
get usedCapacity() {
if (!this.system.uses_inventory_slot) return 0;
if (!this.system.quantity_affects_used_capacity) {
return 1;
};
return this.system.quantity;
};
get availableLocations() {
return [
{ value: null, label: `dotdungeon.location.unknown` },
{ value: `inventory`, label: `dotdungeon.location.inventory` },
{ value: `equipped`, label: `dotdungeon.location.equipped` },
{ value: `storage`, label: `dotdungeon.location.storage` },
];
};
};

View file

@ -1,34 +0,0 @@
import AspectItem from "./Aspect.mjs";
import SpellItem from "./Spell.mjs";
/** @extends {Item} */
export class ItemHandler extends Item {
proxyTargets = {
aspect: AspectItem,
spell: SpellItem,
};
constructor(data, ctx) {
super(data, ctx);
};
/** @type {class|undefined} */
get fn() {
return this.proxyTargets[this.type];
};
async migrateSystemData() {
if (!this.fn?.migrateSystemData) return;
this.fn?.migrateSystemData.bind(this)();
};
async proxyFunction(funcName, ...args) {
if (!this.fn?.[funcName]) return;
return await this.fn?.[funcName].bind(this)(...args);
};
async _preCreate(...args) {
if (!this.fn?._preCreate) return;
return this.fn?._preCreate.bind(this)(...args);
};
};

View file

@ -0,0 +1,15 @@
import { DotDungeonItem } from "./GenericItem.mjs";
export class Material extends DotDungeonItem {
get usedCapacity() {
let affects = game.settings.get(`dotdungeon`, `materialsAffectCapacity`);
return affects ? super.usedCapacity : 0;
};
get availableLocations() {
return [
{ value: null, label: `dotdungeon.location.unknown` },
{ value: `inventory`, label: `dotdungeon.location.inventory` },
];
};
};

View file

@ -1,10 +0,0 @@
import { ItemHandler } from "./Handler.mjs";
/** @this {ItemHandler} */
async function migrateSystemData() {
this.system
};
export default {
migrateSystemData,
};

View file

@ -0,0 +1,47 @@
import { DotDungeonItem } from "./GenericItem.mjs";
import { Aspect } from "./Aspect.mjs";
import { Material } from "./Material.mjs";
const classes = {
aspect: Aspect,
material: Material,
};
const defaultClass = DotDungeonItem;
export const ItemProxy = new Proxy(function () {}, {
construct(target, args) {
const [data] = args;
if (!classes.hasOwnProperty(data.type)) {
return new defaultClass(...args);
}
return new classes[data.type](...args);
},
get(target, prop, receiver) {
if (["create", "createDocuments"].includes(prop)) {
return function (data, options) {
if (data.constructor === Array) {
return data.map(i => ItemProxy.create(i, options))
}
if (!classes.hasOwnProperty(data.type)) {
return defaultClass.create(data, options);
}
return classes[data.type].create(data, options);
};
};
if (prop == Symbol.hasInstance) {
return function (instance) {
if (instance instanceof defaultClass) return true;
return Object.values(classes).some(i => instance instanceof i);
};
};
return defaultClass[prop];
},
});

View file

@ -1,4 +1,7 @@
// Data Models
import { DescribedItemData } from "./models/Item/DescribedItemData.mjs";
import { CommonItemData } from "./models/Item/CommonItemData.mjs";
import { WeaponItemData } from "./models/Item/Weapon.mjs";
import { AspectItemData } from "./models/Item/Aspect.mjs";
import { SpellItemData } from "./models/Item/Spell.mjs";
import { PlayerData } from "./models/Actor/Player.mjs";
@ -7,16 +10,21 @@ import { SyncData } from "./models/Actor/Sync.mjs";
import { MobData } from "./models/Actor/Mob.mjs";
// Main Documents
import { ActorHandler } from "./documents/Actor/Handler.mjs";
import { ItemHandler } from "./documents/Item/Handler.mjs";
import { ActiveEffectProxy } from "./documents/ActiveEffect/_proxy.mjs";
import { ActorProxy } from "./documents/Actor/_proxy.mjs";
import { ItemProxy } from "./documents/Item/_proxy.mjs";
// Character Sheets
import { SpellSheet } from "./sheets/SpellSheet.mjs";
import { AspectSheet } from "./sheets/AspectSheet.mjs";
import { PlayerSheet } from "./sheets/PlayerSheet.mjs";
// Item Sheets
import { UntypedItemSheet } from "./sheets/Items/UntypedItemSheet.mjs";
import { AspectSheet } from "./sheets/Items/AspectSheet.mjs";
import { SpellSheet } from "./sheets/Items/SpellSheet.mjs";
import { PetSheet } from "./sheets/Items/PetSheet.mjs";
// Actor Sheets
import { BasicSyncSheet } from "./sheets/SyncVariations/BasicSyncSheet.mjs";
import { PlayerSheetv2 } from "./sheets/Actors/PC/PlayerSheetV2.mjs";
import { MVPPCSheet } from "./sheets/MVPPCSheet.mjs";
import { MobSheet } from "./sheets/MobSheet.mjs";
import { PetSheet } from "./sheets/PetSheet.mjs";
// Utility imports
import * as hbs from "./handlebars.mjs";
@ -25,31 +33,44 @@ import * as hbs from "./handlebars.mjs";
import "./hooks/hotReload.mjs";
// Misc Imports
import { registerCustomComponents } from "./components/index.mjs";
import loadSettings from "./settings/index.mjs";
import { devInit } from "./hooks/devInit.mjs";
import DOTDUNGEON from "./config.mjs";
Hooks.once(`init`, () => {
Hooks.once(`init`, async () => {
console.debug(`.dungeon | Initializing`);
CONFIG.ActiveEffect.legacyTransferral = false;
loadSettings();
CONFIG.Actor.dataModels.player = PlayerData;
CONFIG.Actor.dataModels.sync = SyncData;
CONFIG.Actor.dataModels.mob = MobData;
CONFIG.Item.dataModels.untyped = DescribedItemData;
CONFIG.Item.dataModels.material = CommonItemData;
CONFIG.Item.dataModels.foil = DescribedItemData;
CONFIG.Item.dataModels.weapon = WeaponItemData;
CONFIG.Item.dataModels.aspect = AspectItemData;
CONFIG.Item.dataModels.spell = SpellItemData;
CONFIG.Item.dataModels.pet = PetItemData;
CONFIG.Actor.documentClass = ActorHandler;
CONFIG.Item.documentClass = ItemHandler;
CONFIG.Actor.documentClass = ActorProxy;
CONFIG.Item.documentClass = ItemProxy;
CONFIG.ActiveEffect.documentClass = ActiveEffectProxy;
CONFIG.DOTDUNGEON = DOTDUNGEON;
// Actors.unregisterSheet("core", ActorSheet);
Actors.registerSheet("dotdungeon", PlayerSheet, {
Actors.registerSheet("dotdungeon", MVPPCSheet, {
makeDefault: true,
types: ["player"],
label: "dotdungeon.sheet-names.PlayerSheet"
label: "dotdungeon.sheet-names.PlayerSheet.MVP"
});
Actors.registerSheet("dotdungeon", PlayerSheetv2, {
makeDefault: false,
types: ["player"],
label: "dotdungeon.sheet-names.PlayerSheet.v2"
});
Actors.registerSheet("dotdungeon", MobSheet, {
makeDefault: true,
@ -62,6 +83,13 @@ Hooks.once(`init`, () => {
label: "dotdungeon.sheet-names.SyncSheet.basic"
});
Items.registerSheet("dotdungeon", UntypedItemSheet, {
makeDefault: true,
label: "dotdungeon.sheet-names.UntypedItemSheet",
});
Items.unregisterSheet("dotdungeon", UntypedItemSheet, {
types: ["aspect"],
});
Items.registerSheet("dotdungeon", AspectSheet, {
makeDefault: true,
types: ["aspect"],
@ -75,11 +103,16 @@ Hooks.once(`init`, () => {
Items.registerSheet("dotdungeon", PetSheet, {
makeDefault: true,
types: ["pet"],
lable: "dotdungeon.sheet-names.PetSheet"
})
label: "dotdungeon.sheet-names.PetSheet"
});
if (true || game.settings.get(`dotdungeon`, `devMode`)) {
devInit();
};
hbs.registerHandlebarsHelpers();
hbs.preloadHandlebarsTemplates();
registerCustomComponents();
});
@ -89,9 +122,9 @@ Hooks.once(`ready`, () => {
let defaultTab = game.settings.get(`dotdungeon`, `defaultTab`);
if (defaultTab) {
if (!ui.sidebar?.tabs?.[defaultTab]) {
console.error(`Couldn't find a sidebar tab with ID:`, defaultTab);
console.error(`.dungeon | Couldn't find a sidebar tab with ID:`, defaultTab);
} else {
console.debug(`Switching sidebar tab to:`, defaultTab);
console.debug(`.dungeon | Switching sidebar tab to:`, defaultTab);
ui.sidebar.tabs[defaultTab].activate();
};
};

View file

@ -7,7 +7,7 @@ export const partials = [
`partials/panel.hbs`,
`items/aspect.hbs`,
// All of the partials for the PC sheet panels
// All of the partials for the PC MVP sheet panels
`actors/char-sheet-mvp/panels/aspect.pc.hbs`,
`actors/char-sheet-mvp/panels/backpack.pc.hbs`,
`actors/char-sheet-mvp/panels/mounts.pc.hbs`,
@ -18,27 +18,32 @@ export const partials = [
`actors/char-sheet-mvp/panels/pets.pc.hbs`,
`actors/char-sheet-mvp/panels/sync.pc.hbs`,
`actors/char-sheet-mvp/panels/weapons.pc.hbs`,
// The v2 PC sheet partials
`actors/char-sheet/v2/partials/stats.v2.pc.hbs`,
`actors/char-sheet/v2/partials/effects.v2.pc.hbs`,
`actors/char-sheet/v2/partials/inventory/inventory.v2.pc.hbs`,
`actors/char-sheet/v2/partials/inventory/player.v2.pc.hbs`,
`actors/char-sheet/v2/partials/inventory/item-list.v2.pc.hbs`,
`actors/char-sheet/v2/partials/inventory/storage.v2.pc.hbs`,
`actors/char-sheet/v2/partials/inventory/items/material.v2.pc.hbs`,
`actors/char-sheet/v2/partials/inventory/items/untyped.v2.pc.hbs`,
`actors/char-sheet/v2/partials/inventory/items/aspect.v2.pc.hbs`,
`actors/char-sheet/v2/partials/inventory/items/weapon.v2.pc.hbs`,
`actors/char-sheet/v2/partials/inventory/items/pet.v2.pc.hbs`,
// The v2 Untyped sheet partials
`items/untyped/v2/tabs/general.v2.untyped.hbs`,
`items/untyped/v2/tabs/details.v2.untyped.hbs`,
`items/untyped/v2/tabs/effects.v2.untyped.hbs`,
`items/untyped/v2/tabs/settings.v2.untyped.hbs`,
];
export const icons = [
`caret-right.svg`,
`garbage-bin.svg`,
`chat-bubble.svg`,
`dice/d4.svg`,
`dice/d6.svg`,
`dice/d8.svg`,
`dice/d10.svg`,
`dice/d12.svg`,
`dice/d20.svg`,
`create.svg`,
`close.svg`,
`edit.svg`,
`sheet.svg`,
];
export const preAliasedPartials = {
"dotdungeon.pc.v2.foil": "actors/char-sheet/v2/partials/inventory/items/untyped.v2.pc.hbs",
};
export async function registerHandlebarsHelpers() {
console.log(Handlebars)
Handlebars.registerHelper(helpers);
};
@ -48,6 +53,10 @@ export async function preloadHandlebarsTemplates() {
const paths = {};
for (const alias in preAliasedPartials) {
paths[alias] = `${pathPrefix}${preAliasedPartials[alias]}`;
};
for ( const partial of partials ) {
console.debug(`Loading partial: ${partial}`);
const path = `${pathPrefix}${partial}`;
@ -69,42 +78,3 @@ export async function preloadHandlebarsTemplates() {
console.groupEnd();
return loadTemplates(paths);
};
/**
* Loads all of the icons that are needed in the handlebars templating to make
* the sheet look nicer.
*
* @returns An object containing icon names to the corresponding HTML data for
* displaying the icon
*/
export async function preloadIcons() {
console.groupCollapsed(`.dungeon | Loading icons for handlebars`);
const pathPrefix = `systems/dotdungeon/assets/`
const parsedIcons = {};
for (const icon of icons) {
const iconName = icon.split(`/`).slice(-1)[0].slice(0, -4);
if (icon.endsWith(`.svg`)) {
try {
const response = await fetchWithTimeout(`${pathPrefix}${icon}`);
if (response.status !== 200) { continue };
const svgData = await response.text();
parsedIcons[iconName] = svgData;
console.debug(`Loaded icon: ${icon}`);
} catch {
console.error(`Failed to fetch/parse icon: ${icon}`);
continue;
};
}
else if (icon.endsWith(`.png`)) {
parsedIcons[iconName] = `<img alt="" src="${pathPrefix}${icon}">`;
console.debug(`Loaded icon: ${icon}`);
}
else {
console.warn(`Icon "${icon}" failed to be handled by a loader`)
};
};
console.groupEnd();
return parsedIcons;
};

View file

@ -2,20 +2,24 @@ import { schemaOptions } from "./schemaOptions.mjs";
import { createArray } from "./createArray.mjs";
import { detailsExpanded } from "./detailsExpanded.mjs";
import { objectValue } from "./objectValue.mjs";
import { toFriendlyDuration } from "./toFriendlyDuration.mjs";
import { handlebarsLocalizer, localizer } from "../utils/localizer.mjs";
import { options } from "./options.mjs";
export default {
// Complex helpers
"dd-schemaOptions": schemaOptions,
"dd-array": createArray,
"dd-toFriendlyDuration": toFriendlyDuration,
"dd-objectValue": objectValue,
"dd-expanded": detailsExpanded,
"dd-i18n": handlebarsLocalizer,
"dd-options": options,
// Simple helpers
"dd-stringify": v => JSON.stringify(v, null, ` `),
"dd-empty": v => v.length == 0,
"dd-set-has": (s, k) => s.has(k),
"dd-empty-state": (v) => v ?? localizer(`dotdungeon.common.empty`),
// Logic helpers
"eq": (a, b) => a == b,

View file

@ -0,0 +1,35 @@
import { localizer } from "../utils/localizer.mjs";
/**
* @typedef {object} Option
* @property {string} [label]
* @property {string|number} value
* @property {boolean} [disabled]
*/
/**
* @param {string | number} selected
* @param {Array<Option | string>} opts
*/
export function options(selected, opts, meta) {
const { localize = false } = meta.hash;
selected = Handlebars.escapeExpression(selected);
const htmlOptions = [];
for (let opt of opts) {
if (foundry.utils.getType(opt) === "string") {
opt = { label: opt, value: opt };
};
opt.value = Handlebars.escapeExpression(opt.value);
htmlOptions.push(
`<option
value="${opt.value}"
${selected === opt.value ? "selected" : ""}
${opt.disabled ? "disabled" : ""}
>
${localize ? localizer(opt.label) : opt.label}
</option>`
);
};
return htmlOptions.join(`\n`);
};

View file

@ -1,26 +0,0 @@
const secondsInAMinute = 60;
const secondsInAnHour = 60 * secondsInAMinute;
/**
* Converts a duration into a more human-friendly format
* @param {number} duration The length of time in seconds
* @returns The human-friendly time string
*/
export function toFriendlyDuration(duration) {
let friendly = ``;
if (duration >= secondsInAnHour) {
let hours = Math.floor(duration / secondsInAnHour);
friendly += `${hours}h`;
duration -= hours * secondsInAnHour;
};
if (duration >= secondsInAMinute) {
let minutes = Math.floor(duration / secondsInAMinute);
friendly += `${minutes}m`;
duration -= minutes * secondsInAMinute;
};
if (duration > 0) {
friendly += `${duration}s`;
};
return friendly;
};

27
module/hooks/devInit.mjs Normal file
View file

@ -0,0 +1,27 @@
/*
Initialization of dev-specific features for the init hook, this is primarily
used to register all of the data sheets of various entity types.
*/
import { GroupDataSheet } from "../sheets/Datasheets/GroupDataSheet.mjs";
import { UntypedDataSheet } from "../sheets/Datasheets/UntypedDataSheet.mjs";
export function devInit() {
Items.registerSheet(
`dotdungeon`,
UntypedDataSheet,
{
types: [`untyped`, `foil`],
label: `dotdungeon.sheet-names.*DataSheet`,
}
);
Actors.registerSheet(
`dotdungeon`,
GroupDataSheet,
{
types: [`sync`],
label: `dotdungeon.sheet-names.*DataSheet`,
}
);
};

View file

@ -1,34 +1,47 @@
import * as hbs from "../handlebars.mjs";
const loaders = {
svg(data) {
const iconName = data.path.split(`/`).slice(-1)[0].slice(0, -4);
console.debug(`.dungeon | hot-reloading icon: ${iconName}`);
Hooks.call(`dd-hmr:svg`, iconName, data);
},
hbs(data) {
if (!hbs.partials.some(p => data.path.endsWith(p))) {
return true;
};
// Compile the new template data.
let template;
try {
template = Handlebars.compile(data.content);
} catch (err) {
return console.error(err);
};
// Re-register our new partial template & cache it.
const alias = data.path
.split(`/`)
.pop()
.split(`.`)
.slice(0, -1)
.reverse()
.join(`.`);
const templateName = `dotdungeon.${alias}`;
Handlebars.registerPartial(templateName, template);
_templateCache[templateName] = template;
return false;
},
js() {window.location.reload()},
mjs() {window.location.reload()},
css(data) {
console.debug(`.dungeon | Hot-reloading CSS: ${data.path}`);
Hooks.call(`dd-hmr:css`, data);
},
};
Hooks.on(`hotReload`, async (data) => {
if (data.extension !== 'hbs') {
return true;
};
if (!hbs.partials.some(p => data.path.endsWith(p))) {
return true;
};
// Compile the new template data.
let template;
try {
template = Handlebars.compile(data.content);
} catch (err) {
return console.error(err);
};
// Re-register our new partial template & cache it.
const alias = data.path
.split(`/`)
.pop()
.split(`.`)
.slice(0, -1)
.reverse()
.join(`.`);
const templateName = `dotdungeon.${alias}`;
Handlebars.registerPartial(templateName, template);
_templateCache[templateName] = template;
return false;
if (!loaders[data.extension]) return;
return loaders[data.extension](data);
});

View file

@ -2,9 +2,6 @@ export class MobData extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
dice: new fields.StringField({
initial: ``,
}),
bonus: new fields.NumberField({
initial: 0,
nullable: false,
@ -25,6 +22,36 @@ export class MobData extends foundry.abstract.TypeDataModel {
initial: ``,
blank: true,
}),
immune: new fields.StringField({
initial: ``,
blank: true,
}),
weak: new fields.StringField({
initial: ``,
blank: true,
}),
bytes: new fields.NumberField({
initial: 0,
min: 0,
}),
description: new fields.StringField({
initial: ``,
blank: true,
}),
dice: new fields.ArrayField(
new fields.SchemaField({
// {count}d{sides} x {repeat}
count: new fields.NumberField({ min: 1 }),
sides: new fields.NumberField({ min: 2 }),
repeat: new fields.NumberField({ min: 1 }),
}),
{ initial: [] }
),
};
};
// Called during create, read, and update
static migrateData(source) {
return source;
};
};

View file

@ -1,4 +1,4 @@
import { MappingField } from "../fields/MappingField.mjs";
import DOTDUNGEON from "../../config.mjs";
function diceChoiceField() {
return new foundry.data.fields.StringField({
@ -6,33 +6,17 @@ function diceChoiceField() {
blank: true,
trim: true,
options() {
return CONFIG.DOTDUNGEON.statDice;
return DOTDUNGEON.statDice;
},
});
};
function trainingLevelField() {
return new foundry.data.fields.StringField({
initial: ``,
blank: true,
trim: true,
options: CONFIG.DOTDUNGEON.trainingLevels,
});
};
function weaponDamageTypeField() {
return new foundry.data.fields.StringField({
initial: ``,
blank: true,
options: [ ``, ...CONFIG.DOTDUNGEON.damageTypes ],
});
};
function ammoTypeField() {
return new foundry.data.fields.StringField({
initial: ``,
blank: true,
options: [ ``, ...CONFIG.DOTDUNGEON.ammoTypes ],
return new foundry.data.fields.NumberField({
initial: 0,
min: -1,
integer: true,
options: Object.values(DOTDUNGEON.trainingLevels),
});
};
@ -40,6 +24,14 @@ export class PlayerData extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
/*
These are special data properties that will be used by ActiveEffects
to modify certain limits within the actor, allowing for neat hacks
that change these
*/
weapon_slots: new fields.NumberField({ initial: 2 }),
inventory_slots: new fields.NumberField({ initial: 0 }),
bytes: new fields.NumberField({
initial: 0,
min: 0,
@ -83,67 +75,18 @@ export class PlayerData extends foundry.abstract.TypeDataModel {
piloting: trainingLevelField(),
})
}),
aspect: new fields.SchemaField({
name: new fields.StringField({ blank: true, trim: true }),
description: new fields.StringField({ blank: true, trim: true }),
deactivateAfter: new fields.NumberField({ min: 0, integer: true}),
used: new fields.BooleanField(),
}),
// ! Delete
roles: new fields.SchemaField({
r1: new fields.StringField({ blank: true, trim: true }),
r2: new fields.StringField({ blank: true, trim: true }),
r3: new fields.StringField({ blank: true, trim: true }),
r4: new fields.StringField({ blank: true, trim: true }),
}),
weapon: new fields.SchemaField({
mainHand: new fields.SchemaField({
name: new fields.StringField({ blank: true, trim: true }),
damage: weaponDamageTypeField(),
ranged: new fields.BooleanField({ initial: false }),
scope: new fields.BooleanField({ initial: false }),
ammo: ammoTypeField(),
}),
offHand: new fields.SchemaField({
name: new fields.StringField({ blank: true, trim: true }),
damage: weaponDamageTypeField(),
ranged: new fields.BooleanField({ initial: false }),
scope: new fields.BooleanField({ initial: false }),
ammo: ammoTypeField(),
}),
ammo: new fields.SchemaField({
quivers: new fields.NumberField({ min: 0, max: 10, integer: true }),
mags: new fields.NumberField({ min: 0, max: 10, integer: true }),
cells: new fields.NumberField({ min: 0, max: 10, integer: true }),
}),
}),
supplies: new fields.NumberField({
initial: 0,
min: 0,
max: 5,
integer: true
}),
materials: new fields.NumberField({
initial: 0,
min: 0,
max: 5,
integer: true
}),
pet: new fields.SchemaField({
name: new fields.StringField(),
info: new fields.StringField(),
}),
transport: new fields.SchemaField({
name: new fields.StringField(),
upkeep: new fields.NumberField({ min: 0, integer: true }),
info: new fields.StringField(),
}),
spells: new MappingField(
new fields.SchemaField({
name: new fields.StringField({ initial: ``, blank: true, trim: true }),
cost: new fields.NumberField({ initial: 0, min: 0 }),
info: new fields.StringField({ initial: ``, blank: true, trim: true }),
})
),
respawns: new fields.SchemaField({
r1: new fields.BooleanField(),
r2: new fields.BooleanField(),
@ -154,7 +97,6 @@ export class PlayerData extends foundry.abstract.TypeDataModel {
integer: true,
initial: 0,
}),
inventoryString: new fields.StringField({ blank: true, trim: true }),
};
};
};

View file

@ -3,10 +3,18 @@ export class SyncData extends foundry.abstract.TypeDataModel {
const fields = foundry.data.fields;
return {
value: new fields.NumberField({
required: true,
integer: true,
initial: 100,
}),
rest_dice: new fields.NumberField({
integer: true,
initial: 0,
min: 0,
}),
milestones_hit: new fields.SetField(
new fields.NumberField({ integer: true, }),
{ initial: [] },
),
};
};
};

View file

@ -1,11 +1,19 @@
export class AspectItemData extends foundry.abstract.TypeDataModel {
import { DescribedItemData } from "./DescribedItemData.mjs";
export class AspectItemData extends DescribedItemData {
static defineSchema() {
const fields = foundry.data.fields;
return {
const parentSchema = super.defineSchema();
// Purge fields that I don't want in this schema
delete parentSchema.quantity;
delete parentSchema.quantity_affects_used_capacity;
delete parentSchema.usage_cost;
return foundry.utils.mergeObject(parentSchema, {
used: new fields.BooleanField({ initial: false }),
/** The number of seconds that the effect of the aspect stays */
deactivateAfter: new fields.NumberField({ nullable: true }),
info: new fields.HTMLField({ nullable: true, blank: false, trim: true }),
};
});
};
};

View file

@ -4,18 +4,46 @@ export class CommonItemData extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
quantity: new fields.NumberField({
initial: 1,
min: 0,
nullable: false,
integer: true,
}),
uses_inventory_slot: new fields.BooleanField({
initial: true,
nullable: false,
}),
quantity_affects_used_capacity: new fields.BooleanField({
initial: true,
nullable: false,
}),
buy: new fields.NumberField({
initial: null,
nullable: true,
integer: true,
}),
usage_cost: new fields.NumberField({
initial: null,
nullable: true,
integer: true,
}),
tier: new fields.StringField({
initial: `simple`,
initial: DOTDUNGEON.defaultItemTier,
nullable: false,
choices: DOTDUNGEON.itemTiers.map(tier => tier.value),
}),
/*
If this property is set to true, the item will be shown in the combat tab
list of items. This is shown whether or not the item is marked as "equipped".
*/
combat_relevant: new fields.BooleanField({
initial: false,
nullable: false,
}),
location: new fields.StringField({
initial: "",
nullable: false,
choices: DOTDUNGEON.itemTiers,
}),
};
};

View file

@ -3,7 +3,7 @@ import { CommonItemData } from "./CommonItemData.mjs";
export class DescribedItemData extends CommonItemData {
static defineSchema() {
const fields = foundry.data.fields;
return mergeObject(super.defineSchema(), {
return foundry.utils.mergeObject(super.defineSchema(), {
description: new fields.StringField({
initial: ``,
blank: true,

View file

@ -3,12 +3,6 @@ import { DescribedItemData } from "./DescribedItemData.mjs";
export class EquipmentItemData extends DescribedItemData {
static defineSchema() {
const fields = foundry.data.fields;
return mergeObject(super.defineSchema(), {
extra_inventory: new fields.NumberField({
initial: null,
nullable: true,
required: false,
}),
});
return foundry.utils.mergeObject(super.defineSchema(), {});
};
};

View file

@ -3,7 +3,13 @@ import { DescribedItemData } from "./DescribedItemData.mjs";
export class PetItemData extends DescribedItemData {
static defineSchema() {
const fields = foundry.data.fields;
return mergeObject(super.defineSchema(), {
const parentSchema = super.defineSchema();
delete parentSchema.quantity;
delete parentSchema.quantity_affects_used_capacity;
delete parentSchema.usage_cost;
return foundry.utils.mergeObject(parentSchema, {
upkeep: new fields.NumberField({ initial: null, nullable: true }),
pokeballd: new fields.BooleanField({ initial: true }),
});

View file

@ -4,7 +4,7 @@ import DOTDUNGEON from "../../config.mjs";
export class SpellItemData extends DescribedItemData {
static defineSchema() {
const fields = foundry.data.fields;
return mergeObject(super.defineSchema(), {
return foundry.utils.mergeObject(super.defineSchema(), {
skill: new fields.StringField({
initial: ``,
blank: true,

View file

@ -1,28 +0,0 @@
import { DescribedItemData } from "./DescribedItemData.mjs";
export class TransportationItemData extends DescribedItemData {
static defineSchema() {
const fields = foundry.data.fields;
return mergeObject(super.defineSchema(), {
single_trip: new fields.NumberField({
initial: null,
nullable: true,
}),
upkeep: new fields.NumberField({
initial: null,
nullable: true,
}),
can_be_in_inventory: new fields.BooleanField({
initial: false,
}),
inventory_slots: new fields.NumberField({
initial: 0,
min: 0,
}),
logon_bonus: new fields.NumberField({
initial: null,
nullable: true,
})
});
};
};

View file

@ -0,0 +1,24 @@
import { DescribedItemData } from "./DescribedItemData.mjs";
import DOTDUNGEON from "../../config.mjs";
export class WeaponItemData extends DescribedItemData {
static defineSchema() {
const fields = foundry.data.fields;
return foundry.utils.mergeObject(super.defineSchema(), {
damage: new fields.StringField({
initial: null,
nullable: true,
blank: true,
options: DOTDUNGEON.damageTypes,
}),
ranged: new fields.BooleanField({ initial: false, }),
scoped: new fields.BooleanField({ initial: false, }),
ammo: new fields.StringField({
initial: null,
nullable: true,
blank: true,
options: DOTDUNGEON.ammoTypes,
}),
});
};
};

View file

@ -129,4 +129,4 @@ export class MappingField extends foundry.data.fields.ObjectField {
path.shift();
return this.model._getField(path);
}
}
};

View file

@ -3,7 +3,7 @@ import { DescribedItemData } from "./DescribedItemData.mjs";
export class TemplateData extends DescribedItemData {
static defineSchema() {
const fields = foundry.data.fields;
return mergeObject(super.defineSchema(), {
return foundry.utils.mergeObject(super.defineSchema(), {
});
};
};

View file

@ -9,6 +9,16 @@ export default function() {
requiresReload: false,
});
game.settings.register(`dotdungeon`, `materialsAffectCapacity`, {
name: `dotdungeon.settings.materialsAffectCapacity.name`,
hint: `dotdungeon.settings.materialsAffectCapacity.description`,
scope: `world`,
config: true,
type: Boolean,
default: true,
requiresReload: false,
});
game.settings.register(`dotdungeon`, `resourcesOrSupplies`, {
name: `dotdungeon.settings.resourcesOrSupplies.name`,
hint: `dotdungeon.settings.resourcesOrSupplies.description`,

View file

@ -0,0 +1,172 @@
import { GenericActorSheet } from "../../GenericActorSheet.mjs";
import DOTDUNGEON from "../../../config.mjs";
import { localizer } from "../../../utils/localizer.mjs";
import { modifierToString } from "../../../utils/modifierToString.mjs";
import { GenericContextMenu } from "../../../utils/GenericContextMenu.mjs";
export class PlayerSheetv2 extends GenericActorSheet {
static get defaultOptions() {
let opts = foundry.utils.mergeObject(
super.defaultOptions,
{
template: `systems/dotdungeon/templates/actors/char-sheet/v2/sheet.hbs`,
tabs: [
{
group: `page`,
navSelector: `nav.page`,
contentSelector: `.page-content`,
initial: `inventory`,
},
{
group: `inventory`,
navSelector: `nav.inventory`,
contentSelector: `.tab[data-tab="inventory"]`,
initial: `player`,
}
],
}
);
opts.classes.push(`style-v3`);
return opts;
};
activateListeners(html) {
super.activateListeners(html);
if (this.document.isEmbedded) return;
if (!this.isEditable) return;
console.debug(`.dungeon | Adding event listeners for Actor: ${this.id}`);
html.find(`.create-ae`).on(`click`, async ($e) => {
console.debug(`Creating an ActiveEffect?`);
const ae = this.actor.createEmbeddedDocuments(`ActiveEffect`, [{name: "Default AE"}]);
ae.sheet.render(true);
});
html.find(`[data-filter-toggle]`).on(`change`, ($e) => {
const target = $e.delegateTarget;
const filter = target.dataset.filterToggle;
this.toggleItemFilter(filter);
this._renderInner();
});
// Make materials be able to be edited/deleted
new GenericContextMenu(html, `.material`, [
{
name: localizer(`dotdungeon.common.edit`),
callback: (html) => {
const data = html[0].dataset;
this.openEmbeddedSheet.bind(this)(data.embeddedId);
},
},
{
name: localizer(`dotdungeon.common.delete`),
callback: (html) => {
const data = html[0].dataset;
this.genericEmbeddedDelete.bind(this)(data.embeddedId);
},
},
]);
};
async getData() {
const ctx = await super.getData();
/** @type {ActorHandler} */
const actor = this.actor;
ctx.preAE = actor.preAE;
ctx.system = actor.system;
ctx.flags = actor.flags;
ctx.items = this.actor.itemTypes;
ctx.computed = {
canChangeGroup: ctx.settings.playersCanChangeGroup || ctx.isGM,
canAddAspect: !this.actor.atAspectLimit,
stats: this.#statData,
itemFilters: this.#itemFilters,
noItemTypesVisible: this._itemTypesHidden.size === DOTDUNGEON.itemFilters.length,
capacity: this.#inventoryCapacity,
};
console.log(ctx)
return ctx;
};
get #statData() {
const stats = [];
const usedDice = new Set(Object.values(this.actor.system.stats));
for (const statName in this.actor.system.stats) {
const stat = {
key: statName,
name: localizer(`dotdungeon.stat.${statName}`),
original: this.actor.preAE.stats[statName],
value: this.actor.system.stats[statName],
};
/*
Determine what dice are available to the user in the dropdown
selector. Disables all dice options that are selected, but not used
by this stat.
*/
stat.dieOptions = [
{ label: `---`, value: `` },
...DOTDUNGEON.statDice.map(die => {
return {
value: die,
label: localizer(`dotdungeon.die.${die}`, { stat: statName }),
disabled: usedDice.has(die) && this.actor.preAE.stats[statName] !== die,
};
})
];
/*
Calculating the data needed in order to display all of the skills
for this character.
*/
stat.skills = [];
for (const skill in this.actor.system.skills[statName]) {
const value = this.actor.system.skills[statName][skill];
stat.skills.push({
key: skill,
name: game.i18n.format(`dotdungeon.skills.${skill}`),
value,
original: this.actor.preAE.skills[statName][skill],
formula: `1` + stat.value + modifierToString(value, { spaces: true }),
rollDisabled: this.actor.preAE.skills[statName][skill] === -1,
});
};
stats.push(stat);
};
return stats;
};
_itemTypesHidden = new Set([`armour`, `equipment`, `structure`, `service`]);
toggleItemFilter(filterName) {
if (this._itemTypesHidden.has(filterName)) {
this._itemTypesHidden.delete(filterName);
} else {
this._itemTypesHidden.add(filterName);
};
this.render();
};
get #itemFilters() {
const types = DOTDUNGEON.itemFilters;
const filters = {};
for (const type of types) {
filters[type] = {
label: localizer(`TYPES.Item.${type}`),
active: !this._itemTypesHidden.has(type),
createLabel: localizer(`dotdungeon.sheet.actor.v2.create-item`, {type}),
};
};
return filters;
};
get #inventoryCapacity() {
return {
used: this.actor.items
.reduce((sum, i) => sum + i.usedCapacity, 0),
max: this.actor.system.inventory_slots,
};
};
}

View file

@ -0,0 +1,31 @@
export class GroupDataSheet extends ActorSheet {
static get defaultOptions() {
let opts = foundry.utils.mergeObject(
super.defaultOptions,
{
template: `systems/dotdungeon/templates/datasheets/actor/group.hbs`,
width: 200,
height: 275
},
);
opts.classes.push(`dotdungeon`, `style-v3`);
return opts;
};
async getData() {
const ctx = {};
ctx.actor = this.actor;
ctx.system = this.actor.system;
ctx.computed = {
milestones_hit_viewable: [...this.actor.system.milestones_hit.values()].join(`, `)
}
ctx.meta = {
idp: this.actor.uuid,
};
return ctx;
};
};

View file

@ -0,0 +1,27 @@
export class UntypedDataSheet extends ItemSheet {
static get defaultOptions() {
let opts = foundry.utils.mergeObject(
super.defaultOptions,
{
template: `systems/dotdungeon/templates/datasheets/untyped.hbs`,
width: 650,
height: 700
},
);
opts.classes.push(`dotdungeon`, `style-v3`);
return opts;
};
async getData() {
const ctx = {};
ctx.item = this.item;
ctx.system = this.item.system;
ctx.meta = {
idp: this.item.uuid,
};
return ctx;
};
};

View file

@ -1,7 +1,18 @@
import { localizer } from "../utils/localizer.mjs";
import DOTDUNGEON from "../config.mjs";
import { preloadIcons } from "../handlebars.mjs";
export class GenericActorSheet extends ActorSheet {
static get defaultOptions() {
let opts = foundry.utils.mergeObject(
super.defaultOptions,
{
scrollY: [`.scrollable`],
}
);
opts.classes.push(`dotdungeon`);
return opts;
};
_expanded = new Set();
#propogatedSettings = [
@ -29,7 +40,7 @@ export class GenericActorSheet extends ActorSheet {
ctx.actor = this.actor;
ctx.config = DOTDUNGEON;
ctx.icons = await preloadIcons();
ctx.icons = {};
return ctx;
};
@ -41,26 +52,49 @@ export class GenericActorSheet extends ActorSheet {
if (!this.isEditable) return;
console.debug(`.dungeon | Generic sheet adding listeners`);
html.find(`summary`).on(`click`, this._handleSummaryToggle.bind(this));
html.find(`.roll`).on(`click`, this._handleRoll.bind(this));
html.find(`[data-embedded-update]`)
.on(`change`, this.actor.genericEmbeddedUpdate.bind(this.actor));
/*
Custom element event listeners because Foundry doesn't listen to them by
default.
*/
html.find(
CONFIG.CACHE.componentListeners.map(n => `${n}[name]`).join(`,`)
).on(`change`, () => this._onChangeInput.bind(this));
/*
Utility event listeners that apply
*/
html.find(`[data-collapse-id]`).on(`click`, this._handleSummaryToggle.bind(this));
html.find(`[data-roll-formula]`).on(`click`, this._handleRoll.bind(this));
html.find(`[data-embedded-update-on="change"]`)
.on(`change`, this.genericEmbeddedUpdate.bind(this));
html.find(`[data-embedded-update-on="blur"]`)
.on(`blur`, this.genericEmbeddedUpdate.bind(this));
html.find(`[data-embedded-delete]`)
.on(`click`, this.actor.genericEmbeddedDelete.bind(this.actor));
.on(`click`, ($e) => {
const id = $e.currentTarget.dataset.embeddedDelete;
this.genericEmbeddedDelete.bind(this)(id);
});
html.find(`[data-embedded-create]`)
.on(`click`, this.actor.genericEmbeddedCreate.bind(this.actor));
.on(`click`, this.genericEmbeddedCreate.bind(this));
html.find(`[data-message-type]`)
.on(`click`, this.actor.genericSendToChat.bind(this.actor));
.on(`click`, this.genericSendToChat.bind(this));
html.find(`[data-embedded-edit]`)
.on(`click`, this.actor.openEmbeddedSheet.bind(this.actor));
.on(`click`, ($e) => {
const id = $e.currentTarget.dataset.embeddedEdit;
this.openEmbeddedSheet.bind(this)(id);
})
html.find(`button[data-increment]`)
.on(`click`, this._incrementValue.bind(this));
html.find(`button[data-decrement]`)
.on(`click`, this._decrementValue.bind(this));
html.find(`button[data-embedded-increment]`)
.on(`click`, this.genericEmbeddedIncrement.bind(this));
html.find(`button[data-embedded-decrement]`)
.on(`click`, this.genericEmbeddedDecrement.bind(this));
};
async _handleRoll($e) {
let data = $e.currentTarget.dataset;
if (!data.rollFormula) {
console.warn(`.dungeon | Element has .roll class with no roll formula`, $e.target);
return;
};
console.debug(`.dungeon | Attempting to roll with formula "${data.rollFormula}"`);
let flavor;
@ -76,21 +110,139 @@ export class GenericActorSheet extends ActorSheet {
});
};
_handleSummaryToggle($e) {
let data = $e.currentTarget.dataset;
let open = $e.currentTarget.parentNode.open;
console.debug(`.dungeon | Collapse ID: ${data.collapseId} (open: ${open})`);
async _incrementValue($e) {
const target = $e.currentTarget;
const data = target.dataset;
const value = getProperty(this.actor, data.increment);
if (typeof value != "number") {
return;
};
this.actor.update({ [data.increment]: value + 1 });
};
/*
This seeming inversion of logic is due to the fact that this handler
gets called before the element is updated to include/reflect the
change, so if the parentNode doesn't actually have it, then we're
opening it and vice-versa.
*/
if (!open) {
async _decrementValue($e) {
const target = $e.currentTarget;
const data = target.dataset;
const value = getProperty(this.actor, data.decrement);
if (typeof value != "number") {
return;
};
this.actor.update({ [data.decrement]: value - 1 });
};
async _handleSummaryToggle($e) {
$e.stopPropagation();
let target = $e.currentTarget;
let parent = target.closest(`.collapse`);
let data = target.dataset;
console.debug(`.dungeon | Collapse ID: ${data.collapseId}`);
if (!this._expanded.has(data.collapseId)) {
this._expanded.add(data.collapseId);
parent.setAttribute(`open`, ``);
} else {
this._expanded.delete(data.collapseId);
parent.removeAttribute(`open`, ``);
};
};
async openEmbeddedSheet(item_id) {
let item = await fromUuid(item_id);
item?.sheet.render(true);
};
async genericEmbeddedCreate($event) {
const data = $event.currentTarget.dataset;
if (!this[`createCustom${data.embeddedCreate}`]) {
this.actor.createEmbeddedItem({
type: data.embeddedCreate,
name: localizer(
`dotdungeon.default.name`,
{ document: `Item`, type: data.embeddedCreate }
),
});
} else {
this[`createCustom${data.embeddedCreate}`]($event);
};
};
async genericEmbeddedUpdate($event) {
const target = $event.currentTarget;
const data = target.dataset;
const item = await fromUuid(data.embeddedId);
let value = target.value;
switch (target.type) {
case "checkbox": value = target.checked; break;
};
await item?.update({ [data.embeddedUpdate]: value });
};
async genericEmbeddedIncrement($event) {
const target = $event.currentTarget;
const data = target.dataset;
const item = await fromUuid(data.embeddedId);
const value = getProperty(item, data.embeddedIncrement);
if (typeof value != "number") {
return;
};
await item?.update({ [data.embeddedIncrement]: value + 1 });
};
async genericEmbeddedDecrement($event) {
const target = $event.currentTarget;
const data = target.dataset;
const item = await fromUuid(data.embeddedId);
const value = getProperty(item, data.embeddedDecrement);
if (typeof value != "number") {
return;
};
await item?.update({ [data.embeddedDecrement]: value - 1 });
};
async genericEmbeddedDelete(item_uuid) {
let item = await fromUuid(item_uuid);
if (!item) {
ui.notifications.error(
`dotdungeon.notification.error.item-not-found`,
{ console: false }
);
return;
};
Dialog.confirm({
title: game.i18n.format(
`dotdungeon.dialogs.${item.type}.delete.title`,
item
),
content: game.i18n.format(
`dotdungeon.dialogs.${item.type}.delete.content`,
item
),
yes: () => {
item.delete();
},
defaultYes: false,
});
};
async genericSendToChat($event) {
const data = $event.currentTarget.dataset;
const type = data.messageType;
if (this[`send${type}ToChat`]) {
return await this[`send${type}ToChat`]($event);
};
if (!data.messageContent) {
console.warn(`.dungeon | Tried to send a chat message with no content`);
return;
};
let message = await ChatMessage.create({
content: data.messageContent,
flavor: data.messageFlavor,
speaker: { actor: this.actor },
});
message.render();
};
};

View file

@ -2,7 +2,7 @@ import { GenericItemSheet } from "./GenericItemSheet.mjs";
export class AspectSheet extends GenericItemSheet {
static get defaultOptions() {
let opts = mergeObject(
let opts = foundry.utils.mergeObject(
super.defaultOptions,
{
template: `systems/dotdungeon/templates/items/aspect.hbs`,
@ -22,14 +22,7 @@ export class AspectSheet extends GenericItemSheet {
};
async getData() {
const ctx = {};
const item = this.item;
ctx.item = item;
ctx.system = item.system;
ctx.flags = item.flags;
console.log(item.uuid, `context:`, ctx);
const ctx = await super.getData();
return ctx;
};
};

View file

@ -0,0 +1,86 @@
import { DialogManager } from "../../utils/DialogManager.mjs";
import DOTDUNGEON from "../../config.mjs";
export class GenericItemSheet extends ItemSheet {
_expanded = new Set();
#propogatedSettings = [
`devMode`,
`showAvatarOnSheet`,
`playersCanChangeGroup`,
`resourcesOrSupplies`,
];
async getData() {
const ctx = {};
// Send all of the settings that sheets need into their context
ctx.settings = {};
for (const setting of this.#propogatedSettings) {
ctx.settings[setting] = game.settings.get(`dotdungeon`, setting);
};
ctx.isGM = game.users.current.hasRole(CONST.USER_ROLES.ASSISTANT);
ctx.meta = {
expanded: this._expanded,
idp: this.item.uuid,
};
ctx.item = this.item;
ctx.system = this.item.system;
ctx.flags = this.item.flags;
ctx.effects = this.item.effects;
ctx.config = DOTDUNGEON;
ctx.icons = {};
return ctx;
};
activateListeners(html) {
super.activateListeners(html);
if (!this.isEditable) return;
console.debug(`.dungeon | Adding event listeners for Generic Item: ${this.id}`);
html.find(`button[data-increment]`)
.on(`click`, this._incrementValue.bind(this));
html.find(`button[data-decrement]`)
.on(`click`, this._decrementValue.bind(this));
html.find(`[data-help-id]`)
.on(`click`, this._helpPopup.bind(this));
};
async _incrementValue($e) {
const target = $e.currentTarget;
const data = target.dataset;
const value = getProperty(this.actor, data.increment);
if (typeof value != "number") {
return;
};
this.actor.update({ [data.increment]: value + 1 });
};
async _decrementValue($e) {
const target = $e.currentTarget;
const data = target.dataset;
const value = getProperty(this.actor, data.decrement);
if (typeof value != "number") {
return;
};
this.actor.update({ [data.decrement]: value - 1 });
};
async _helpPopup($e) {
const target = $e.currentTarget;
const data = target.dataset;
if (!data.helpId) return;
DialogManager.helpDialog(
data.helpId,
data.helpContent,
data.helpTitle
);
};
};

View file

@ -2,7 +2,7 @@ import { GenericItemSheet } from "./GenericItemSheet.mjs";
export class PetSheet extends GenericItemSheet {
static get defaultOptions() {
let opts = mergeObject(
let opts = foundry.utils.mergeObject(
super.defaultOptions,
{
template: `systems/dotdungeon/templates/items/pet.hbs`,
@ -23,10 +23,6 @@ export class PetSheet extends GenericItemSheet {
async getData() {
const ctx = await super.getData();
ctx.item = this.item;
ctx.system = this.item.system;
ctx.flags = this.item.flags;
return ctx;
};
};

View file

@ -2,7 +2,7 @@ import { GenericItemSheet } from "./GenericItemSheet.mjs";
export class SpellSheet extends GenericItemSheet {
static get defaultOptions() {
let opts = mergeObject(
let opts = foundry.utils.mergeObject(
super.defaultOptions,
{
template: `systems/dotdungeon/templates/items/spell.hbs`,
@ -23,10 +23,6 @@ export class SpellSheet extends GenericItemSheet {
async getData() {
const ctx = await super.getData();
ctx.item = this.item;
ctx.system = this.item.system;
ctx.flags = this.item.flags;
return ctx;
};
};

Some files were not shown because too many files have changed in this diff Show more