diff --git a/.gitignore b/.gitignore
index 4c1e822..4beb05c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,7 +6,7 @@ references/
/.*/
!/.vscode/
!/.github/
-/foundry.js
+/*.ref.*
*.lock
*.zip
diff --git a/assets/caret-down.svg b/assets/caret-down.svg
deleted file mode 100644
index 415d3db..0000000
--- a/assets/caret-down.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/assets/caret-right.svg b/assets/caret-right.svg
deleted file mode 100644
index 7d1d59b..0000000
--- a/assets/caret-right.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/assets/chat-bubble.svg b/assets/chat-bubble.svg
deleted file mode 100644
index 8dde604..0000000
--- a/assets/chat-bubble.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/assets/close.svg b/assets/close.svg
deleted file mode 100644
index f6c80ed..0000000
--- a/assets/close.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/assets/dice/d10.svg b/assets/dice/d10.svg
index 96a39a1..3debc8e 100644
--- a/assets/dice/d10.svg
+++ b/assets/dice/d10.svg
@@ -1,3 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/assets/dice/d12.svg b/assets/dice/d12.svg
index dac2e4c..df2787c 100644
--- a/assets/dice/d12.svg
+++ b/assets/dice/d12.svg
@@ -1,3 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/assets/dice/d20.svg b/assets/dice/d20.svg
index 82cf8b3..a829cdf 100644
--- a/assets/dice/d20.svg
+++ b/assets/dice/d20.svg
@@ -1,3 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/assets/dice/d4.svg b/assets/dice/d4.svg
index 3388bda..f31809b 100644
--- a/assets/dice/d4.svg
+++ b/assets/dice/d4.svg
@@ -1,3 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/assets/dice/d6.svg b/assets/dice/d6.svg
index bea7528..00dfed7 100644
--- a/assets/dice/d6.svg
+++ b/assets/dice/d6.svg
@@ -1,3 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/assets/dice/d8.svg b/assets/dice/d8.svg
index ca3b00b..7731f96 100644
--- a/assets/dice/d8.svg
+++ b/assets/dice/d8.svg
@@ -1,3 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/assets/edit.svg b/assets/edit.svg
deleted file mode 100644
index 7cc344b..0000000
--- a/assets/edit.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/assets/garbage-bin.svg b/assets/garbage-bin.svg
deleted file mode 100644
index b9268a5..0000000
--- a/assets/garbage-bin.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/assets/minus.svg b/assets/minus.svg
deleted file mode 100644
index 171613e..0000000
--- a/assets/minus.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/assets/sheet.svg b/assets/sheet.svg
deleted file mode 100644
index eaf555b..0000000
--- a/assets/sheet.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/assets/sources.txt b/assets/sources.txt
index b002fc2..2896d5f 100644
--- a/assets/sources.txt
+++ b/assets/sources.txt
@@ -1,12 +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/)
- caret-down.svg (https://thenounproject.com/icon/arrow-caret-down-1143911/)
+ 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/)
@@ -17,21 +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
- minus.svg (https://thenounproject.com/icon/minus-1727966/)
+ 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
\ No newline at end of file
+Muhammad Ahsanu Nadia:
+ ui/help.svg (https://thenounproject.com/icon/help-6778522/)
diff --git a/assets/ui/caret/down.svg b/assets/ui/caret/down.svg
new file mode 100644
index 0000000..5c15836
--- /dev/null
+++ b/assets/ui/caret/down.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/ui/caret/right.svg b/assets/ui/caret/right.svg
new file mode 100644
index 0000000..3b19a49
--- /dev/null
+++ b/assets/ui/caret/right.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/ui/chat-bubble.svg b/assets/ui/chat-bubble.svg
new file mode 100644
index 0000000..a9182c1
--- /dev/null
+++ b/assets/ui/chat-bubble.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/ui/close.svg b/assets/ui/close.svg
new file mode 100644
index 0000000..3082802
--- /dev/null
+++ b/assets/ui/close.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/ui/garbage-bin.svg b/assets/ui/garbage-bin.svg
new file mode 100644
index 0000000..dd96a44
--- /dev/null
+++ b/assets/ui/garbage-bin.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/ui/help.svg b/assets/ui/help.svg
new file mode 100644
index 0000000..bd06071
--- /dev/null
+++ b/assets/ui/help.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/ui/minus.svg b/assets/ui/minus.svg
new file mode 100644
index 0000000..d1d3e94
--- /dev/null
+++ b/assets/ui/minus.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/ui/pencil.svg b/assets/ui/pencil.svg
new file mode 100644
index 0000000..455379f
--- /dev/null
+++ b/assets/ui/pencil.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/create.svg b/assets/ui/plus.svg
similarity index 100%
rename from assets/create.svg
rename to assets/ui/plus.svg
diff --git a/assets/ui/sheet.svg b/assets/ui/sheet.svg
new file mode 100644
index 0000000..32a3268
--- /dev/null
+++ b/assets/ui/sheet.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/langs/en-ca.2.json b/langs/en-ca.2.json
index ae5e9b7..dce0efa 100644
--- a/langs/en-ca.2.json
+++ b/langs/en-ca.2.json
@@ -81,10 +81,26 @@
"send-to-chat": "Send to Chat",
"edit": "Edit",
"delete": "Delete",
- "empty": "---"
+ "reset": "Reset",
+ "empty": "---",
+ "help": "Help",
+ "gm": "Server",
+ "view-larger": "View Larger"
},
"sheet-names": {
- "UntypedDataSheet": "Data Sheet"
+ "*DataSheet": "Data Sheet"
+ },
+ "help-tooltips": {
+ "calculated-capacity": {
+ "title": "What is Calculated Capacity?",
+ "content": "
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.
"
+ }
+ },
+ "delete": {
+ "ActiveEffect": {
+ "title": "Delete Effect",
+ "content": "Are you sure you would like to delete the active effect: {name}
"
+ }
}
},
"TYPES": {
@@ -105,6 +121,9 @@
"legendaryItem": "Legendary Item",
"spell": "Spell",
"untyped": "Custom"
+ },
+ "ActiveEffect": {
+ "base": "Effect"
}
}
}
\ No newline at end of file
diff --git a/module/components/incrementer.mjs b/module/components/incrementer.mjs
index 26069ee..68e426a 100644
--- a/module/components/incrementer.mjs
+++ b/module/components/incrementer.mjs
@@ -85,8 +85,8 @@ export class DotDungeonIncrementer extends StyledShadowElement(HTMLElement) {
input.value = value;
// plus button
- const increment = document.createElement("dd-icon");
- increment.setAttribute(`name`, `create`);
+ 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;
@@ -95,7 +95,7 @@ export class DotDungeonIncrementer extends StyledShadowElement(HTMLElement) {
// minus button
const decrement = document.createElement(DotDungeonIcon.elementName);
- decrement.setAttribute(`name`, `minus`);
+ decrement.setAttribute(`name`, `ui/minus`);
decrement.setAttribute(`var:size`, `0.75rem`);
decrement.setAttribute(`var:fill`, `currentColor`);
decrement.ariaHidden = true;
@@ -127,9 +127,6 @@ export class DotDungeonIncrementer extends StyledShadowElement(HTMLElement) {
this.#input.value = value;
this.value = value;
this.dispatchEvent(new Event(`change`, { bubbles: true }));
-
- // NOTE: This may be really annoying, in that case, remove it later
- this.blur();
};
/** @param {Event} $e */
diff --git a/module/dialogs/DiceList.mjs b/module/dialogs/DiceList.mjs
index f9793de..3c305c8 100644
--- a/module/dialogs/DiceList.mjs
+++ b/module/dialogs/DiceList.mjs
@@ -12,7 +12,7 @@ export class DiceList extends GenericDialog {
};
static get defaultOptions() {
- const opts = mergeObject({
+ const opts = foundry.utils.mergeObject({
...super.defaultOptions,
template: `systems/dotdungeon/templates/dialogs/diceList.hbs`,
width: 275,
diff --git a/module/documents/ActiveEffect/GenericActiveEffect.mjs b/module/documents/ActiveEffect/GenericActiveEffect.mjs
new file mode 100644
index 0000000..8ee70f3
--- /dev/null
+++ b/module/documents/ActiveEffect/GenericActiveEffect.mjs
@@ -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 };
+};
diff --git a/module/documents/ActiveEffect/_proxy.mjs b/module/documents/ActiveEffect/_proxy.mjs
new file mode 100644
index 0000000..4b51b54
--- /dev/null
+++ b/module/documents/ActiveEffect/_proxy.mjs
@@ -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];
+ },
+});
diff --git a/module/documents/Actor/GenericActor.mjs b/module/documents/Actor/GenericActor.mjs
index d52b185..171af63 100644
--- a/module/documents/Actor/GenericActor.mjs
+++ b/module/documents/Actor/GenericActor.mjs
@@ -1,4 +1,15 @@
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] : [];
diff --git a/module/documents/Actor/Player.mjs b/module/documents/Actor/Player.mjs
index ff54481..2c5840d 100644
--- a/module/documents/Actor/Player.mjs
+++ b/module/documents/Actor/Player.mjs
@@ -1,8 +1,22 @@
import { DotDungeonActor } from "./GenericActor.mjs";
-import { DotDungeonItem } from "../Item/GenericItem.mjs";
export class Player extends DotDungeonActor {
+ 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,
diff --git a/module/documents/Actor/Sync.mjs b/module/documents/Actor/Sync.mjs
index 1542b3e..171a67c 100644
--- a/module/documents/Actor/Sync.mjs
+++ b/module/documents/Actor/Sync.mjs
@@ -1,4 +1,5 @@
import { DotDungeonActor } from "./GenericActor.mjs";
+import { syncMilestones } from "../../config.mjs";
export class Sync extends DotDungeonActor {
async useRestDie() {
diff --git a/module/documents/Item/Material.mjs b/module/documents/Item/Material.mjs
index 15d2a58..c6c5b72 100644
--- a/module/documents/Item/Material.mjs
+++ b/module/documents/Item/Material.mjs
@@ -5,4 +5,11 @@ export class Material extends DotDungeonItem {
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` },
+ ];
+ };
};
diff --git a/module/dotdungeon.mjs b/module/dotdungeon.mjs
index aa79b99..8731314 100644
--- a/module/dotdungeon.mjs
+++ b/module/dotdungeon.mjs
@@ -10,6 +10,7 @@ import { SyncData } from "./models/Actor/Sync.mjs";
import { MobData } from "./models/Actor/Mob.mjs";
// Main Documents
+import { ActiveEffectProxy } from "./documents/ActiveEffect/_proxy.mjs";
import { ActorProxy } from "./documents/Actor/_proxy.mjs";
import { ItemProxy } from "./documents/Item/_proxy.mjs";
@@ -40,6 +41,7 @@ import DOTDUNGEON from "./config.mjs";
Hooks.once(`init`, async () => {
console.debug(`.dungeon | Initializing`);
+ CONFIG.ActiveEffect.legacyTransferral = false;
loadSettings();
@@ -55,6 +57,7 @@ Hooks.once(`init`, async () => {
CONFIG.Item.dataModels.pet = PetItemData;
CONFIG.Actor.documentClass = ActorProxy;
CONFIG.Item.documentClass = ItemProxy;
+ CONFIG.ActiveEffect.documentClass = ActiveEffectProxy;
CONFIG.DOTDUNGEON = DOTDUNGEON;
@@ -103,16 +106,13 @@ Hooks.once(`init`, async () => {
label: "dotdungeon.sheet-names.PetSheet"
});
- if (game.settings.get(`dotdungeon`, `devMode`)) {
+ if (true || game.settings.get(`dotdungeon`, `devMode`)) {
devInit();
};
hbs.registerHandlebarsHelpers();
hbs.preloadHandlebarsTemplates();
registerCustomComponents();
-
- CONFIG.CACHE ??= {};
- CONFIG.CACHE.icons = await hbs.preloadIcons();
});
diff --git a/module/handlebars.mjs b/module/handlebars.mjs
index de34f62..cdaa1b7 100644
--- a/module/handlebars.mjs
+++ b/module/handlebars.mjs
@@ -43,25 +43,6 @@ export const preAliasedPartials = {
"dotdungeon.pc.v2.foil": "actors/char-sheet/v2/partials/inventory/items/untyped.v2.pc.hbs",
};
-export const icons = [
- `caret-right.svg`,
- `caret-down.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`,
- `minus.svg`,
-];
-
-
export async function registerHandlebarsHelpers() {
Handlebars.registerHelper(helpers);
};
@@ -97,38 +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() {
- 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;
- } catch {
- console.error(`.dungeon | Failed to fetch/parse icon: ${icon}`);
- continue;
- };
- }
- else if (icon.endsWith(`.png`)) {
- parsedIcons[iconName] = ` `;
- }
- else {
- console.warn(`.dungeon | Icon "${icon}" failed to be handled by a loader`)
- };
- };
-
- return parsedIcons;
-};
diff --git a/module/hooks/devInit.mjs b/module/hooks/devInit.mjs
index 4f604e0..b7ef326 100644
--- a/module/hooks/devInit.mjs
+++ b/module/hooks/devInit.mjs
@@ -3,6 +3,7 @@ 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() {
@@ -11,7 +12,16 @@ export function devInit() {
UntypedDataSheet,
{
types: [`untyped`, `foil`],
- label: `dotdungeon.sheet-names.UntypedDataSheet`,
+ label: `dotdungeon.sheet-names.*DataSheet`,
+ }
+ );
+
+ Actors.registerSheet(
+ `dotdungeon`,
+ GroupDataSheet,
+ {
+ types: [`sync`],
+ label: `dotdungeon.sheet-names.*DataSheet`,
}
);
};
diff --git a/module/models/Item/Aspect.mjs b/module/models/Item/Aspect.mjs
index eb1ffed..92b3eac 100644
--- a/module/models/Item/Aspect.mjs
+++ b/module/models/Item/Aspect.mjs
@@ -10,7 +10,7 @@ export class AspectItemData extends DescribedItemData {
delete parentSchema.quantity_affects_used_capacity;
delete parentSchema.usage_cost;
- return mergeObject(parentSchema, {
+ 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 }),
diff --git a/module/models/Item/DescribedItemData.mjs b/module/models/Item/DescribedItemData.mjs
index ebfce48..eb913a0 100644
--- a/module/models/Item/DescribedItemData.mjs
+++ b/module/models/Item/DescribedItemData.mjs
@@ -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,
diff --git a/module/models/Item/Equipment.mjs b/module/models/Item/Equipment.mjs
index 82b58de..309fd3b 100644
--- a/module/models/Item/Equipment.mjs
+++ b/module/models/Item/Equipment.mjs
@@ -3,6 +3,6 @@ import { DescribedItemData } from "./DescribedItemData.mjs";
export class EquipmentItemData extends DescribedItemData {
static defineSchema() {
const fields = foundry.data.fields;
- return mergeObject(super.defineSchema(), {});
+ return foundry.utils.mergeObject(super.defineSchema(), {});
};
};
diff --git a/module/models/Item/Pet.mjs b/module/models/Item/Pet.mjs
index 886e761..34c6de5 100644
--- a/module/models/Item/Pet.mjs
+++ b/module/models/Item/Pet.mjs
@@ -9,7 +9,7 @@ export class PetItemData extends DescribedItemData {
delete parentSchema.quantity_affects_used_capacity;
delete parentSchema.usage_cost;
- return mergeObject(parentSchema, {
+ return foundry.utils.mergeObject(parentSchema, {
upkeep: new fields.NumberField({ initial: null, nullable: true }),
pokeballd: new fields.BooleanField({ initial: true }),
});
diff --git a/module/models/Item/Spell.mjs b/module/models/Item/Spell.mjs
index 6bd90f6..f96381f 100644
--- a/module/models/Item/Spell.mjs
+++ b/module/models/Item/Spell.mjs
@@ -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,
diff --git a/module/models/Item/Weapon.mjs b/module/models/Item/Weapon.mjs
index 5b9cf67..20db6b7 100644
--- a/module/models/Item/Weapon.mjs
+++ b/module/models/Item/Weapon.mjs
@@ -4,7 +4,7 @@ import DOTDUNGEON from "../../config.mjs";
export class WeaponItemData extends DescribedItemData {
static defineSchema() {
const fields = foundry.data.fields;
- return mergeObject(super.defineSchema(), {
+ return foundry.utils.mergeObject(super.defineSchema(), {
damage: new fields.StringField({
initial: null,
nullable: true,
diff --git a/module/models/template.mjs b/module/models/template.mjs
index f3cea2a..77340ee 100644
--- a/module/models/template.mjs
+++ b/module/models/template.mjs
@@ -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(), {
});
};
};
diff --git a/module/sheets/Actors/PC/PlayerSheetV2.mjs b/module/sheets/Actors/PC/PlayerSheetV2.mjs
index 9dd14ac..ac1a378 100644
--- a/module/sheets/Actors/PC/PlayerSheetV2.mjs
+++ b/module/sheets/Actors/PC/PlayerSheetV2.mjs
@@ -6,7 +6,7 @@ import { GenericContextMenu } from "../../../utils/GenericContextMenu.mjs";
export class PlayerSheetv2 extends GenericActorSheet {
static get defaultOptions() {
- let opts = mergeObject(
+ let opts = foundry.utils.mergeObject(
super.defaultOptions,
{
template: `systems/dotdungeon/templates/actors/char-sheet/v2/sheet.hbs`,
@@ -39,9 +39,8 @@ export class PlayerSheetv2 extends GenericActorSheet {
html.find(`.create-ae`).on(`click`, async ($e) => {
console.debug(`Creating an ActiveEffect?`);
- ActiveEffect.implementation.create({
- name: "Default AE",
- }, { parent: this.actor, renderSheet: true });
+ 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;
@@ -74,6 +73,7 @@ export class PlayerSheetv2 extends GenericActorSheet {
/** @type {ActorHandler} */
const actor = this.actor;
+ ctx.preAE = actor.preAE;
ctx.system = actor.system;
ctx.flags = actor.flags;
ctx.items = this.actor.itemTypes;
@@ -97,6 +97,7 @@ export class PlayerSheetv2 extends GenericActorSheet {
const stat = {
key: statName,
name: localizer(`dotdungeon.stat.${statName}`),
+ original: this.actor.preAE.stats[statName],
value: this.actor.system.stats[statName],
};
@@ -111,7 +112,7 @@ export class PlayerSheetv2 extends GenericActorSheet {
return {
value: die,
label: localizer(`dotdungeon.die.${die}`, { stat: statName }),
- disabled: usedDice.has(die) && this.actor.system.stats[statName] !== die,
+ disabled: usedDice.has(die) && this.actor.preAE.stats[statName] !== die,
};
})
];
@@ -127,8 +128,9 @@ export class PlayerSheetv2 extends GenericActorSheet {
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: value === -1,
+ rollDisabled: this.actor.preAE.skills[statName][skill] === -1,
});
};
diff --git a/module/sheets/Datasheets/GroupDataSheet.mjs b/module/sheets/Datasheets/GroupDataSheet.mjs
new file mode 100644
index 0000000..6c9527a
--- /dev/null
+++ b/module/sheets/Datasheets/GroupDataSheet.mjs
@@ -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;
+ };
+};
diff --git a/module/sheets/GenericActorSheet.mjs b/module/sheets/GenericActorSheet.mjs
index 1f39bf3..2010304 100644
--- a/module/sheets/GenericActorSheet.mjs
+++ b/module/sheets/GenericActorSheet.mjs
@@ -3,7 +3,7 @@ import DOTDUNGEON from "../config.mjs";
export class GenericActorSheet extends ActorSheet {
static get defaultOptions() {
- let opts = mergeObject(
+ let opts = foundry.utils.mergeObject(
super.defaultOptions,
{
scrollY: [`.scrollable`],
@@ -40,7 +40,7 @@ export class GenericActorSheet extends ActorSheet {
ctx.actor = this.actor;
ctx.config = DOTDUNGEON;
- ctx.icons = CONFIG.CACHE.icons;
+ ctx.icons = {};
return ctx;
};
@@ -57,8 +57,8 @@ export class GenericActorSheet extends ActorSheet {
default.
*/
html.find(
- CONFIG.CACHE.componentListeners.join(`,`)
- ).on(`change`, this._onChangeInput.bind(this));
+ CONFIG.CACHE.componentListeners.map(n => `${n}[name]`).join(`,`)
+ ).on(`change`, () => this._onChangeInput.bind(this));
/*
Utility event listeners that apply
@@ -83,7 +83,6 @@ export class GenericActorSheet extends ActorSheet {
const id = $e.currentTarget.dataset.embeddedEdit;
this.openEmbeddedSheet.bind(this)(id);
})
- .on(`click`, this.openEmbeddedSheet.bind(this));
html.find(`button[data-increment]`)
.on(`click`, this._incrementValue.bind(this));
html.find(`button[data-decrement]`)
diff --git a/module/sheets/Items/AspectSheet.mjs b/module/sheets/Items/AspectSheet.mjs
index c43a01c..2bf8638 100644
--- a/module/sheets/Items/AspectSheet.mjs
+++ b/module/sheets/Items/AspectSheet.mjs
@@ -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`,
diff --git a/module/sheets/Items/GenericItemSheet.mjs b/module/sheets/Items/GenericItemSheet.mjs
index ab67779..936bd6c 100644
--- a/module/sheets/Items/GenericItemSheet.mjs
+++ b/module/sheets/Items/GenericItemSheet.mjs
@@ -1,3 +1,4 @@
+import { DialogManager } from "../../utils/DialogManager.mjs";
import DOTDUNGEON from "../../config.mjs";
export class GenericItemSheet extends ItemSheet {
@@ -10,13 +11,6 @@ export class GenericItemSheet extends ItemSheet {
`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 = {};
@@ -36,10 +30,57 @@ export class GenericItemSheet extends ItemSheet {
ctx.item = this.item;
ctx.system = this.item.system;
ctx.flags = this.item.flags;
+ ctx.effects = this.item.effects;
ctx.config = DOTDUNGEON;
- ctx.icons = CONFIG.CACHE.icons;
+ 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
+ );
+ };
};
diff --git a/module/sheets/Items/PetSheet.mjs b/module/sheets/Items/PetSheet.mjs
index 169516c..a2db3b9 100644
--- a/module/sheets/Items/PetSheet.mjs
+++ b/module/sheets/Items/PetSheet.mjs
@@ -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`,
diff --git a/module/sheets/Items/SpellSheet.mjs b/module/sheets/Items/SpellSheet.mjs
index cabf2db..8e92831 100644
--- a/module/sheets/Items/SpellSheet.mjs
+++ b/module/sheets/Items/SpellSheet.mjs
@@ -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`,
diff --git a/module/sheets/Items/UntypedItemSheet.mjs b/module/sheets/Items/UntypedItemSheet.mjs
index 90061b0..5ae0f24 100644
--- a/module/sheets/Items/UntypedItemSheet.mjs
+++ b/module/sheets/Items/UntypedItemSheet.mjs
@@ -1,9 +1,11 @@
import { GenericContextMenu } from "../../utils/GenericContextMenu.mjs";
+import { DialogManager } from "../../utils/DialogManager.mjs";
import { GenericItemSheet } from "./GenericItemSheet.mjs";
+import { localizer } from "../../utils/localizer.mjs";
export class UntypedItemSheet extends GenericItemSheet {
static get defaultOptions() {
- let opts = mergeObject(
+ let opts = foundry.utils.mergeObject(
super.defaultOptions,
{
template: `systems/dotdungeon/templates/items/untyped/v2/index.hbs`,
@@ -28,22 +30,78 @@ export class UntypedItemSheet extends GenericItemSheet {
new GenericContextMenu(html, `.photo.panel`, [
{
- name: `View Larger`,
- callback: (html) => {
- console.log(`.dungeon | View Larger`);
+ name: localizer(`dotdungeon.common.view-larger`),
+ callback: () => {
+ (new ImagePopout(this.item.img)).render(true);
},
},
{
- name: `Change Photo`,
+ name: localizer(`dotdungeon.common.edit`),
condition: () => this.isEditable,
- callback: (html) => {
- console.log(`.dungeon | Change Photo`);
+ callback: () => {
+ const fp = new FilePicker({
+ callback: (path) => {
+ this.item.update({"img": path});
+ },
+ });
+ fp.render(true);
},
},
+ {
+ name: localizer(`dotdungeon.common.reset`),
+ condition: () => this.isEditable,
+ callback: () => {
+ console.log(`.dungeon | Reset Item Image`)
+ },
+ }
]);
if (!this.isEditable) return;
console.debug(`.dungeon | Adding event listeners for Untyped Item: ${this.item.id}`);
+
+ html.find(`.create-ae`).on(`click`, async () => {
+ await this.item.createEmbeddedDocuments(
+ `ActiveEffect`,
+ [{name: localizer(`dotdungeon.default.name`, { document: `ActiveEffect`, type: `base` })}],
+ { renderSheet: true }
+ );
+ });
+
+ new GenericContextMenu(html, `.effect.panel`, [
+ {
+ name: localizer(`dotdungeon.common.edit`),
+ callback: async (html) => {
+ (await fromUuid(html.closest(`.effect`)[0].dataset.embeddedId))?.sheet.render(true);
+ },
+ },
+ {
+ name: localizer(`dotdungeon.common.delete`),
+ callback: async (html) => {
+ const target = html.closest(`.effect`)[0];
+ const data = target.dataset;
+ const id = data.embeddedId;
+ const doc = await fromUuid(id);
+ DialogManager.createOrFocus(
+ `${doc.uuid}-delete`,
+ {
+ title: localizer(`dotdungeon.delete.ActiveEffect.title`, doc),
+ content: localizer(`dotdungeon.delete.ActiveEffect.content`, doc),
+ buttons: {
+ yes: {
+ label: localizer(`Yes`),
+ callback() {
+ doc.delete();
+ },
+ },
+ no: {
+ label: localizer(`No`),
+ }
+ }
+ }
+ );
+ },
+ }
+ ]);
};
async getData() {
diff --git a/module/sheets/MVPPCSheet.mjs b/module/sheets/MVPPCSheet.mjs
index 3572b25..a5f05f5 100644
--- a/module/sheets/MVPPCSheet.mjs
+++ b/module/sheets/MVPPCSheet.mjs
@@ -5,7 +5,7 @@ export class MVPPCSheet extends GenericActorSheet {
/** @override {ActorHandler} actor */
static get defaultOptions() {
- let opts = mergeObject(
+ let opts = foundry.utils.mergeObject(
super.defaultOptions,
{
template: `systems/dotdungeon/templates/actors/char-sheet-mvp/sheet.hbs`
diff --git a/module/sheets/MobSheet.mjs b/module/sheets/MobSheet.mjs
index b2ecc06..b2f2213 100644
--- a/module/sheets/MobSheet.mjs
+++ b/module/sheets/MobSheet.mjs
@@ -3,7 +3,7 @@ import { DiceList } from "../dialogs/DiceList.mjs";
export class MobSheet extends GenericActorSheet {
static get defaultOptions() {
- let opts = mergeObject(
+ let opts = foundry.utils.mergeObject(
super.defaultOptions,
{
template: `systems/dotdungeon/templates/actors/mobs/main.hbs`,
diff --git a/module/sheets/SyncVariations/AbstractSyncSheet.mjs b/module/sheets/SyncVariations/AbstractSyncSheet.mjs
index 53bfdf1..80e372b 100644
--- a/module/sheets/SyncVariations/AbstractSyncSheet.mjs
+++ b/module/sheets/SyncVariations/AbstractSyncSheet.mjs
@@ -2,7 +2,7 @@ import { GenericActorSheet } from "../GenericActorSheet.mjs";
export class AbstractSyncSheet extends GenericActorSheet {
static get defaultOptions() {
- let opts = mergeObject(
+ let opts = foundry.utils.mergeObject(
super.defaultOptions,
{
width: 200,
diff --git a/module/utils/DialogManager.mjs b/module/utils/DialogManager.mjs
new file mode 100644
index 0000000..7c40407
--- /dev/null
+++ b/module/utils/DialogManager.mjs
@@ -0,0 +1,83 @@
+import { localizer } from "./localizer.mjs";
+
+/**
+ * A utility class that allows managing Dialogs that are created for various
+ * purposes such as deleting items, help popups, etc. This is a singleton class
+ * that upon instantiating after the first time will just return the first instance
+ */
+export class DialogManager {
+
+ /** @type {Map} */
+ static #dialogs = new Map();
+
+ /**
+ * Focuses a dialog if it already exists, or creates a new one and renders it.
+ *
+ * @param {string} dialogId The ID to associate with the dialog, should be unique
+ * @param {object} data The data to pass to the Dialog constructor
+ * @param {DialogOptions} opts The options to pass to the Dialog constructor
+ * @returns {Dialog} The Dialog instance
+ */
+ static async createOrFocus(dialogId, data, opts = {}) {
+ if (DialogManager.#dialogs.has(dialogId)) {
+ const dialog = DialogManager.#dialogs.get(dialogId);
+ dialog.bringToTop();
+ return dialog;
+ };
+
+ /*
+ This makes sure that if I provide a close function as a part of the data,
+ that the dialog still gets removed from the set once it's closed, otherwise
+ it could lead to dangling references that I don't care to keep. Or if I don't
+ provide the close function, it just sets the function as there isn't anything
+ extra that's needed to be called.
+ */
+ if (data?.close) {
+ const provided = data.close;
+ data.close = () => {
+ DialogManager.#dialogs.delete(dialogId);
+ provided();
+ };
+ }
+ else {
+ data.close = () => DialogManager.#dialogs.delete(dialogId);
+ };
+
+ // Create the Dialog with the modified data
+ const dialog = new Dialog(data, opts);
+ DialogManager.#dialogs.set(dialogId, dialog);
+ dialog.render(true);
+ return dialog;
+ };
+
+ /**
+ * Closes a dialog if it is rendered
+ *
+ * @param {string} dialogId The ID of the dialog to close
+ */
+ static async close(dialogId) {
+ const dialog = DialogManager.#dialogs.get(dialogId);
+ dialog?.close();
+ };
+
+ static async helpDialog(
+ helpId,
+ helpContent,
+ helpTitle = `dotdungeon.common.help`,
+ localizationData = {},
+ ) {
+ DialogManager.createOrFocus(
+ helpId,
+ {
+ title: localizer(helpTitle, localizationData),
+ content: localizer(helpContent, localizationData),
+ buttons: {},
+ },
+ { resizable: true, }
+ );
+ };
+
+ static get size() {
+ return DialogManager.#dialogs.size;
+ }
+};
diff --git a/module/utils/localizer.mjs b/module/utils/localizer.mjs
index 550c1cb..7cfebb0 100644
--- a/module/utils/localizer.mjs
+++ b/module/utils/localizer.mjs
@@ -18,12 +18,20 @@ export function localizer(key, args = {}, depth = 0) {
return localized;
};
+ /*
+ Helps prevent recursion on the same key so that we aren't doing excess work.
+ */
+ const localizedSubkeys = new Map();
for (const match of subkeys) {
const subkey = match.groups.key;
- localized =
- localized.slice(0, match.index)
- + localizer(subkey, args, depth + 1)
- + localized.slice(match.index + subkey.length + 1)
+ if (localizedSubkeys.has(subkey)) continue;
+ localizedSubkeys.set(subkey, localizer(subkey, args, depth + 1));
};
- return localized;
+
+ return localized.replace(
+ localizerConfig.subKeyPattern,
+ (_fullMatch, subkey) => {
+ return localizedSubkeys.get(subkey);
+ }
+ );
};
diff --git a/styles/mixins/_partials.scss b/styles/mixins/_partials.scss
index 8932b3e..e006802 100644
--- a/styles/mixins/_partials.scss
+++ b/styles/mixins/_partials.scss
@@ -18,9 +18,9 @@
@mixin sub-nav($parent, $group, $display) {
nav.#{$group} {
@include material.elevate(1);
- display: none;
+ display: none !important;
}
&:has(nav.#{$parent} .active[data-tab="#{$group}"]) nav.#{$group} {
- display: #{$display};
+ display: #{$display} !important;
}
}
diff --git a/styles/sheets/actor/char-sheet/v2/pages/inventory.scss b/styles/sheets/actor/char-sheet/v2/pages/inventory.scss
index 3a1b829..57626fd 100644
--- a/styles/sheets/actor/char-sheet/v2/pages/inventory.scss
+++ b/styles/sheets/actor/char-sheet/v2/pages/inventory.scss
@@ -49,11 +49,11 @@
&__list {
&--material {
display: grid;
- grid-template-columns: 1fr 1fr;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
}
- &--untyped, &--aspect {
+ &--untyped, &--aspect, &--foil, &--weapon, &--pet {
display: flex;
gap: 8px;
flex-direction: column;
@@ -164,8 +164,8 @@
@include material.elevate(1);
padding: 8px;
gap: 8px;
- display: grid;
- grid-template-columns: 1fr min-content 50px min-content;
+ display: flex;
+ justify-content: space-between;
align-items: center;
border-radius: 4px;
diff --git a/styles/v3/elements/button.scss b/styles/v3/elements/button.scss
index b758bee..33ad097 100644
--- a/styles/v3/elements/button.scss
+++ b/styles/v3/elements/button.scss
@@ -1,43 +1,46 @@
@use "../mixins/material" as material;
-.dotdungeon.style-v3 > .window-content button {
- @include material.elevate(2);
- align-items: center;
- border-radius: 4px;
- border: none;
- box-sizing: border-box;
- color: inherit;
- cursor: pointer;
- display: inline-flex;
- font-family: sans-serif;
- gap: 4px;
- justify-content: center;
- margin: 0;
- outline: none;
- padding: 4px 8px;
- transition: all 200ms ease-in-out;
- width: initial;
+.dotdungeon.style-v3 > .window-content {
+ button, a.button {
+ @include material.elevate(2);
+ align-items: center;
+ border-radius: 4px;
+ border: none;
+ box-sizing: border-box;
+ color: inherit;
+ cursor: pointer;
+ display: inline-flex;
+ font-family: sans-serif;
+ gap: 4px;
+ justify-content: center;
+ margin: 0;
+ outline: none;
+ padding: 4px 8px;
+ transition: all 200ms ease-in-out;
+ width: initial;
- &:hover, &:focus-visible {
- @include material.elevate(4);
- }
- &:active {
- @include material.elevate(6);
- }
+ &:hover, &:focus-visible {
+ @include material.elevate(4);
+ text-shadow: none;
+ }
+ &:active {
+ @include material.elevate(6);
+ }
- &:disabled {
- opacity: 50%;
- cursor: default;
- }
+ &:disabled {
+ opacity: 50%;
+ cursor: default;
+ }
- /* Icon buttons don't use Material styling */
- &.icon {
- @include material.undo;
- padding: 4px;
-
- &:focus-visible {
+ /* Icon buttons don't use Material styling */
+ &.icon {
@include material.undo;
- // TODO : Accessible focus state
+ padding: 4px;
+
+ &:focus-visible {
+ @include material.undo;
+ // TODO : Accessible focus state
+ }
}
}
}
diff --git a/styles/v3/elements/checkbox.scss b/styles/v3/elements/checkbox.scss
new file mode 100644
index 0000000..d3bae5f
--- /dev/null
+++ b/styles/v3/elements/checkbox.scss
@@ -0,0 +1,24 @@
+.dotdungeon.style-v3 {
+ input[type="checkbox"] {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ border-radius: 2px;
+ margin: 0;
+ cursor: pointer;
+
+ background: var(--elevation-8dp-bg);
+ position: relative;
+ &:checked::before {
+ content: "";
+ background: var(--checkbox-checked);
+ border-radius: 3px;
+ $margin: 4px;
+ top: $margin;
+ bottom: $margin;
+ left: $margin;
+ right: $margin;
+ position: absolute;
+ }
+ }
+}
diff --git a/styles/v3/elements/utilities.scss b/styles/v3/elements/utilities.scss
index 2a3cb42..32cc792 100644
--- a/styles/v3/elements/utilities.scss
+++ b/styles/v3/elements/utilities.scss
@@ -6,4 +6,7 @@
.text-center {
text-align: center;
}
+ .text-right {
+ text-align: right;
+ }
}
diff --git a/styles/v3/index.scss b/styles/v3/index.scss
index 1814eac..85ec4bf 100644
--- a/styles/v3/index.scss
+++ b/styles/v3/index.scss
@@ -5,6 +5,7 @@
/* Element-Styling */
@use "./elements/utilities.scss";
@use "./elements/button.scss";
+@use "./elements/checkbox.scss";
@use "./elements/select.scss";
@use "./elements/text-input.scss";
@use "./elements/number-input.scss";
diff --git a/styles/v3/layouts/items/untyped/v2.scss b/styles/v3/layouts/items/untyped/v2.scss
index 8c18cd3..d94bf49 100644
--- a/styles/v3/layouts/items/untyped/v2.scss
+++ b/styles/v3/layouts/items/untyped/v2.scss
@@ -44,6 +44,7 @@
%flex-col {
display: flex;
flex-direction: column;
+ gap: 8px;
}
@include utils.tab("details") {
@@ -56,7 +57,25 @@
}
}
- @include utils.tab("settings") {
+ @include utils.tab("effects") {
@extend %flex-col;
}
+
+ @include utils.tab("settings") {
+ @extend %flex-col;
+
+ .capacity-usage, .quantity-capacity, .combat-relevant {
+ display: flex;
+ align-items: center;
+ }
+
+ .capacity {
+ &--calculated {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: 8px;
+ }
+ }
+ }
}
diff --git a/styles/v3/themes/dark.css b/styles/v3/themes/dark.css
index a5cbc65..374056f 100644
--- a/styles/v3/themes/dark.css
+++ b/styles/v3/themes/dark.css
@@ -4,4 +4,6 @@
--surface: #121212;
--on-surface: white;
+
+ --checkbox-checked: #00d300;
}
diff --git a/system.json b/system.json
index 3c80e4b..5d3387c 100644
--- a/system.json
+++ b/system.json
@@ -2,7 +2,7 @@
"id": "dotdungeon",
"title": ".dungeon",
"description": "",
- "version": "0.0.7",
+ "version": "0.0.9",
"download": "https://github.com/Oliver-Akins/foundry.dungeon/releases/latest/download/dotdungeon.zip",
"manifest": "https://github.com/Oliver-Akins/foundry.dungeon/releases/latest/download/system.json",
"url": "https://github.com/Oliver-Akins/foundry.dungeon",
diff --git a/templates/actors/char-sheet/v2/partials/inventory/item-list.v2.pc.hbs b/templates/actors/char-sheet/v2/partials/inventory/item-list.v2.pc.hbs
index 3cbaac5..73926f9 100644
--- a/templates/actors/char-sheet/v2/partials/inventory/item-list.v2.pc.hbs
+++ b/templates/actors/char-sheet/v2/partials/inventory/item-list.v2.pc.hbs
@@ -17,9 +17,7 @@
data-tooltip="{{filter.createLabel}}"
data-tooltip-direction="LEFT"
>
-
- {{{ @root.icons.create }}}
-
+
diff --git a/templates/actors/char-sheet/v2/partials/inventory/items/aspect.v2.pc.hbs b/templates/actors/char-sheet/v2/partials/inventory/items/aspect.v2.pc.hbs
index 5d61f2d..ff106e6 100644
--- a/templates/actors/char-sheet/v2/partials/inventory/items/aspect.v2.pc.hbs
+++ b/templates/actors/char-sheet/v2/partials/inventory/items/aspect.v2.pc.hbs
@@ -13,9 +13,7 @@
tabindex="0"
aria-label="{{dd-i18n 'dotdungeon.sheet.actor.v2.toggle-item-information' item}}"
>
-
- {{{ icons.caret-right }}}
-
+
{{item.name}}
diff --git a/templates/actors/char-sheet/v2/partials/inventory/items/material.v2.pc.hbs b/templates/actors/char-sheet/v2/partials/inventory/items/material.v2.pc.hbs
index 272702a..ea0a8b3 100644
--- a/templates/actors/char-sheet/v2/partials/inventory/items/material.v2.pc.hbs
+++ b/templates/actors/char-sheet/v2/partials/inventory/items/material.v2.pc.hbs
@@ -7,52 +7,11 @@
>
{{item.name}}
- {{#if (eq item.system.quantity 0)}}
-
-
- {{{ icons.garbage-bin }}}
-
-
- {{else}}
-
-
- {{{ icons.minus }}}
-
-
- {{/if}}
-
-
-
- {{{ icons.create }}}
-
-
+ >
diff --git a/templates/actors/char-sheet/v2/partials/inventory/items/pet.v2.pc.hbs b/templates/actors/char-sheet/v2/partials/inventory/items/pet.v2.pc.hbs
index fd481e7..dc0e1a8 100644
--- a/templates/actors/char-sheet/v2/partials/inventory/items/pet.v2.pc.hbs
+++ b/templates/actors/char-sheet/v2/partials/inventory/items/pet.v2.pc.hbs
@@ -13,9 +13,7 @@
tabindex="0"
aria-label="{{dd-i18n 'dotdungeon.sheet.actor.v2.toggle-item-information' item}}"
>
-
- {{{ icons.caret-right }}}
-
+
{{item.name}}
diff --git a/templates/actors/char-sheet/v2/partials/inventory/items/untyped.v2.pc.hbs b/templates/actors/char-sheet/v2/partials/inventory/items/untyped.v2.pc.hbs
index 9907578..de3abdc 100644
--- a/templates/actors/char-sheet/v2/partials/inventory/items/untyped.v2.pc.hbs
+++ b/templates/actors/char-sheet/v2/partials/inventory/items/untyped.v2.pc.hbs
@@ -13,9 +13,7 @@
tabindex="0"
aria-label="{{dd-i18n 'dotdungeon.sheet.actor.v2.toggle-item-information' item}}"
>
-
- {{{ icons.caret-right }}}
-
+
{{item.name}}
diff --git a/templates/actors/char-sheet/v2/partials/inventory/items/weapon.v2.pc.hbs b/templates/actors/char-sheet/v2/partials/inventory/items/weapon.v2.pc.hbs
index 36707d8..6b0fe0f 100644
--- a/templates/actors/char-sheet/v2/partials/inventory/items/weapon.v2.pc.hbs
+++ b/templates/actors/char-sheet/v2/partials/inventory/items/weapon.v2.pc.hbs
@@ -13,9 +13,7 @@
tabindex="0"
aria-label="{{dd-i18n 'dotdungeon.sheet.actor.v2.toggle-item-information' item}}"
>
-
- {{{ icons.caret-right }}}
-
+
{{item.name}}
diff --git a/templates/actors/char-sheet/v2/partials/stats.v2.pc.hbs b/templates/actors/char-sheet/v2/partials/stats.v2.pc.hbs
index 8db48ad..6353120 100644
--- a/templates/actors/char-sheet/v2/partials/stats.v2.pc.hbs
+++ b/templates/actors/char-sheet/v2/partials/stats.v2.pc.hbs
@@ -7,11 +7,14 @@
name="system.stats.{{stat.key}}"
class="e-2dp dice-select"
>
- {{{dd-options stat.value stat.dieOptions}}}
+ {{{dd-options stat.original stat.dieOptions}}}
Roll
@@ -32,7 +35,7 @@
class="e-2dp skill__training"
>
{{{dd-options
- skill.value
+ skill.original
@root.config.trainingLevels
localize=true
}}}
@@ -41,6 +44,8 @@
type="button"
class="e-2dp skill__roll"
{{disabled skill.rollDisabled}}
+ data-roll-formula="{{skill.formula}}"
+ data-roll-label="Skill Roll : {{skill.name}}"
>
{{#if skill.rollDisabled}}
{{dd-i18n "dotdungeon.sheet.actor.v2.skill-roll-locked"}}
diff --git a/templates/datasheets/actor/group.hbs b/templates/datasheets/actor/group.hbs
new file mode 100644
index 0000000..5cd9830
--- /dev/null
+++ b/templates/datasheets/actor/group.hbs
@@ -0,0 +1,36 @@
+
\ No newline at end of file
diff --git a/templates/items/untyped/v2/index.hbs b/templates/items/untyped/v2/index.hbs
index d57f46e..c8509ac 100644
--- a/templates/items/untyped/v2/index.hbs
+++ b/templates/items/untyped/v2/index.hbs
@@ -10,11 +10,11 @@
diff --git a/templates/items/untyped/v2/tabs/details.v2.untyped.hbs b/templates/items/untyped/v2/tabs/details.v2.untyped.hbs
index d8bf937..87134ee 100644
--- a/templates/items/untyped/v2/tabs/details.v2.untyped.hbs
+++ b/templates/items/untyped/v2/tabs/details.v2.untyped.hbs
@@ -15,8 +15,8 @@
id="{{meta.idp}}-purchase-cost"
>
{{else}}
- Purchase Cost
- {{dd-empty-state system.buy}}
+ Purchase Cost
+ {{dd-empty-state system.buy}}
{{/if}}
@@ -35,12 +35,12 @@
id="{{meta.idp}}-usage-cost"
>
{{else}}
- Usage Cost
- {{dd-empty-state system.usage_cost}}
+ Usage Cost
+ {{dd-empty-state system.usage_cost}}
{{/if}}
- Rarity
+ Rarity
{{#if meta.isEditable}}
{{else}}
- {{dd-i18n (concat "dotdungeon.rarity." system.tier)}}
+ {{dd-i18n (concat "dotdungeon.rarity." system.tier)}}
{{/if}}
{{#if meta.isEmbedded}}
diff --git a/templates/items/untyped/v2/tabs/effects.v2.untyped.hbs b/templates/items/untyped/v2/tabs/effects.v2.untyped.hbs
index 9206962..8f142a1 100644
--- a/templates/items/untyped/v2/tabs/effects.v2.untyped.hbs
+++ b/templates/items/untyped/v2/tabs/effects.v2.untyped.hbs
@@ -1,3 +1,34 @@
- Effects Tab
+ {{#each effects as | effect |}}
+
+
+ {{effect.name}}
+
+
+ {{ifThen effect.disabled "Disabled" "Enabled"}}
+
+ {{!-- TODO: For some reason this embedded update logic was failing
+
+ {{ effect.name }}
+
+
+
+
+ --}}
+
+ {{/each}}
+
+
+ Create Effect
+
diff --git a/templates/items/untyped/v2/tabs/settings.v2.untyped.hbs b/templates/items/untyped/v2/tabs/settings.v2.untyped.hbs
index e9fd907..b24584a 100644
--- a/templates/items/untyped/v2/tabs/settings.v2.untyped.hbs
+++ b/templates/items/untyped/v2/tabs/settings.v2.untyped.hbs
@@ -1,22 +1,61 @@
{{#if meta.isEmbedded}}
- Useful in Combat?
+
+ Useful in Combat?
+
+
+
{{/if}}
{{#if isGM}}
- Uses Capacity?
-
- (GM Only)
+
+ Uses Capacity?
+
+ (GM Only)
+
+
+
- Quantity Affects Capacity?
-
- (GM Only)
+
+ Quantity Affects Capacity?
+
+ (GM Only)
+
+
+
{{/if}}
-
- Total Capacity Used:
+
+
Capacity Used:
+
+
+
{{item.usedCapacity}}