Adding Prettier

* Added prettier with automatic useage on pre-commit to avoid style breakage
* Ran Prettier on the project
This commit is contained in:
WBHarry 2025-05-23 18:57:50 +02:00 committed by GitHub
parent 820c2df1f4
commit b24cdcc9ed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
136 changed files with 13929 additions and 12206 deletions

1
.husky/pre-commit Normal file
View file

@ -0,0 +1 @@
npx lint-staged

5
.prettierignore Normal file
View file

@ -0,0 +1,5 @@
node_modules
package-lock.json
package.json
.github
*.hbs

13
.prettierrc Normal file
View file

@ -0,0 +1,13 @@
{
"trailingComma": "none",
"tabWidth": 4,
"useTabs": false,
"semi": true,
"singleQuote": true,
"quoteProps": "consistent",
"bracketSpacing": true,
"arrowParens": "avoid",
"printWidth": 120,
"endOfLine": "lf",
"bracketSameLine": true
}

View file

@ -1,27 +1,47 @@
# Daggerheart # Daggerheart
#### For Foundry VTT #### For Foundry VTT
This is a repo for a Foundry VTT implementation of daggerheart. It is not associated with critical role This is a repo for a Foundry VTT implementation of daggerheart. It is not associated with critical role
or darrington press. or darrington press.
# Table Of Contents # Table Of Contents
- [Overview](#overview) - [Overview](#overview)
- [Developer Guide](#developer-guide) - [Developer Guide](#developer-guide)
# Overview # Overview
# Developer Guide # Developer Guide
#### Coding Practises
##### Branches And Pull Requests
During pre-release development, we are making use of `main` as the development branch. Once release is getting closer we will instead be making a `dev` branch to base development from to make `main` more stable.
When you work on an issue or feature, start from `main` and make a new branch. Branches should be topically named and with the associated Issue number if it relates to an Issue. EX: `#6/Level-Up-Bugginess`.
---
Once you're finished with an issue or feature, open a Pull Request on Github for that branch.
The Reviewers Team will be approving submissions. This is mainly since we have a wide spread of experience with system building and the system itself, and we do want the system to become something great. As time goes on, more collaborators are likely to be added as reviewers.
#### Setup #### Setup
- Open a terminal in the directory with the repo `cd <path>/<to>/<repo>` - Open a terminal in the directory with the repo `cd <path>/<to>/<repo>`
- NOTE: The repo should be placed in the system files are or somewhere else and a link (if on linux) is placed in the system directory - NOTE: The repo should be placed in the system files are or somewhere else and a link (if on linux) is placed in the system directory
- NOTE: Linux link can be made using `ln -snf <path to development folder> daggerheart` inside the system folder - NOTE: Linux link can be made using `ln -snf <path to development folder> daggerheart` inside the system folder
- Install npm `npm install` - Install npm `npm install`
- Update package.json to match your profile - Update package.json to match your profile
``` ```
"start": "concurrently \"rollup -c --watch\" \"node C:/FoundryDev/resources/app/main.js --dataPath=C:/FoundryDevFiles --noupnp\" \"gulp\"", "start": "concurrently \"rollup -c --watch\" \"node C:/FoundryDev/resources/app/main.js --dataPath=C:/FoundryDevFiles --noupnp\" \"gulp\"",
"start-test": "node C:/FoundryDev/resources/app/main.js --dataPath=C:/FoundryDevFiles && rollup -c --watch && gulp", "start-test": "node C:/FoundryDev/resources/app/main.js --dataPath=C:/FoundryDevFiles && rollup -c --watch && gulp",
``` ```
- Replace `C:/FoundryDev/resources/app/main.js` with `<your>/<path>/<to>/<foundry>/<main.js>` - Replace `C:/FoundryDev/resources/app/main.js` with `<your>/<path>/<to>/<foundry>/<main.js>`
- The main is likely in `<Foundry Install Location>/resouces/app/main.js` - The main is likely in `<Foundry Install Location>/resouces/app/main.js`
- Replace `--dataPath=C:/FoundryDevFiles` with `<your>/<path>/<to>/<foundry>/<data>` - Replace `--dataPath=C:/FoundryDevFiles` with `<your>/<path>/<to>/<foundry>/<data>`
@ -29,5 +49,4 @@ or darrington press.
Now you should be able to build the app using `npm start` Now you should be able to build the app using `npm start`
[Foundry VTT Website][1] [Foundry VTT Website][1]
[1]: https://foundryvtt.com/ [1]: https://foundryvtt.com/

View file

@ -17,10 +17,13 @@ Hooks.once('init', () => {
game.system.api = { game.system.api = {
applications, applications,
models, models,
documents, documents
} };
CONFIG.statusEffects = Object.values(SYSTEM.GENERAL.conditions).map(x => ({ ...x, name: game.i18n.localize(x.name) })); CONFIG.statusEffects = Object.values(SYSTEM.GENERAL.conditions).map(x => ({
...x,
name: game.i18n.localize(x.name)
}));
CONFIG.Item.documentClass = documents.DhpItem; CONFIG.Item.documentClass = documents.DhpItem;
CONFIG.Item.dataModels = { CONFIG.Item.dataModels = {
@ -33,45 +36,45 @@ Hooks.once('init', () => {
miscellaneous: models.DhpMiscellaneous, miscellaneous: models.DhpMiscellaneous,
consumable: models.DhpConsumable, consumable: models.DhpConsumable,
weapon: models.DhpWeapon, weapon: models.DhpWeapon,
armor: models.DhpArmor, armor: models.DhpArmor
}; };
const { Items, Actors } = foundry.documents.collections; const { Items, Actors } = foundry.documents.collections;
Items.unregisterSheet("core", foundry.appv1.sheets.ItemSheet); Items.unregisterSheet('core', foundry.appv1.sheets.ItemSheet);
Items.registerSheet(SYSTEM.id, applications.DhpAncestry, {types: ["ancestry"], makeDefault: true}); Items.registerSheet(SYSTEM.id, applications.DhpAncestry, { types: ['ancestry'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.DhpCommunity, {types: ["community"], makeDefault: true}); Items.registerSheet(SYSTEM.id, applications.DhpCommunity, { types: ['community'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.DhpClassSheet, {types: ["class"], makeDefault: true}); Items.registerSheet(SYSTEM.id, applications.DhpClassSheet, { types: ['class'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.DhpSubclass, {types: ["subclass"], makeDefault: true}); Items.registerSheet(SYSTEM.id, applications.DhpSubclass, { types: ['subclass'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.DhpFeatureSheet, {types: ["feature"], makeDefault: true}); Items.registerSheet(SYSTEM.id, applications.DhpFeatureSheet, { types: ['feature'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.DhpDomainCardSheet, {types: ["domainCard"], makeDefault: true}); Items.registerSheet(SYSTEM.id, applications.DhpDomainCardSheet, { types: ['domainCard'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.DhpMiscellaneous, {types: ["miscellaneous"], makeDefault: true}); Items.registerSheet(SYSTEM.id, applications.DhpMiscellaneous, { types: ['miscellaneous'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.DhpConsumable, {types: ["consumable"], makeDefault: true}); Items.registerSheet(SYSTEM.id, applications.DhpConsumable, { types: ['consumable'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.DhpWeapon, {types: ["weapon"], makeDefault: true}); Items.registerSheet(SYSTEM.id, applications.DhpWeapon, { types: ['weapon'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.DhpArmor, {types: ["armor"], makeDefault: true}); Items.registerSheet(SYSTEM.id, applications.DhpArmor, { types: ['armor'], makeDefault: true });
CONFIG.Actor.documentClass = documents.DhpActor; CONFIG.Actor.documentClass = documents.DhpActor;
CONFIG.Actor.dataModels = { CONFIG.Actor.dataModels = {
pc: models.DhpPC, pc: models.DhpPC,
adversary: models.DhpAdversary, adversary: models.DhpAdversary,
environment: models.DhpEnvironment, environment: models.DhpEnvironment
}; };
Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet); Actors.unregisterSheet('core', foundry.appv1.sheets.ActorSheet);
Actors.registerSheet(SYSTEM.id, applications.DhpPCSheet, {types: ["pc"], makeDefault: true}); Actors.registerSheet(SYSTEM.id, applications.DhpPCSheet, { types: ['pc'], makeDefault: true });
Actors.registerSheet(SYSTEM.id, applications.DhpAdversarySheet, {types: ["adversary"], makeDefault: true}); Actors.registerSheet(SYSTEM.id, applications.DhpAdversarySheet, { types: ['adversary'], makeDefault: true });
Actors.registerSheet(SYSTEM.id, applications.DhpEnvironment, {types: ["environment"], makeDefault: true}); Actors.registerSheet(SYSTEM.id, applications.DhpEnvironment, { types: ['environment'], makeDefault: true });
CONFIG.Combat.dataModels = { CONFIG.Combat.dataModels = {
base: models.DhpCombat, base: models.DhpCombat
}; };
CONFIG.Combatant.dataModels = { CONFIG.Combatant.dataModels = {
base: models.DhpCombatant, base: models.DhpCombatant
}; };
CONFIG.ChatMessage.dataModels ={ CONFIG.ChatMessage.dataModels = {
dualityRoll: models.DhpDualityRoll, dualityRoll: models.DhpDualityRoll,
adversaryRoll: models.DhpAdversaryRoll, adversaryRoll: models.DhpAdversaryRoll,
abilityUse: models.DhpAbilityUse, abilityUse: models.DhpAbilityUse
}; };
CONFIG.ChatMessage.documentClass = applications.DhpChatMessage; CONFIG.ChatMessage.documentClass = applications.DhpChatMessage;
@ -90,22 +93,24 @@ Hooks.once('init', () => {
return preloadHandlebarsTemplates(); return preloadHandlebarsTemplates();
}); });
Hooks.once('dicesoniceready', () => { Hooks.once('dicesoniceready', () => {});
});
Hooks.on(socketEvent.GMUpdate, async (action, uuid, update) => { Hooks.on(socketEvent.GMUpdate, async (action, uuid, update) => {
if(game.user.isGM){ if (game.user.isGM) {
const document = uuid ? await fromUuid(uuid) : null; const document = uuid ? await fromUuid(uuid) : null;
switch(action){ switch (action) {
case GMUpdateEvent.UpdateDocument: case GMUpdateEvent.UpdateDocument:
if(document && update){ if (document && update) {
await document.update(update); await document.update(update);
} }
break; break;
case GMUpdateEvent.UpdateFear: case GMUpdateEvent.UpdateFear:
if(game.user.isGM){ if (game.user.isGM) {
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear, Math.max(Math.min(update, 6), 0)); await game.settings.set(
SYSTEM.id,
SYSTEM.SETTINGS.gameSettings.Resources.Fear,
Math.max(Math.min(update, 6), 0)
);
Hooks.callAll(socketEvent.DhpFearUpdate); Hooks.callAll(socketEvent.DhpFearUpdate);
await game.socket.emit(`system.${SYSTEM.id}`, { action: socketEvent.DhpFearUpdate }); await game.socket.emit(`system.${SYSTEM.id}`, { action: socketEvent.DhpFearUpdate });
} }
@ -114,27 +119,27 @@ Hooks.on(socketEvent.GMUpdate, async (action, uuid, update) => {
} }
}); });
const preloadHandlebarsTemplates = async function() { const preloadHandlebarsTemplates = async function () {
return foundry.applications.handlebars.loadTemplates([ return foundry.applications.handlebars.loadTemplates([
"systems/daggerheart/templates/sheets/parts/attributes.hbs", 'systems/daggerheart/templates/sheets/parts/attributes.hbs',
"systems/daggerheart/templates/sheets/parts/defense.hbs", 'systems/daggerheart/templates/sheets/parts/defense.hbs',
"systems/daggerheart/templates/sheets/parts/armor.hbs", 'systems/daggerheart/templates/sheets/parts/armor.hbs',
"systems/daggerheart/templates/sheets/parts/experience.hbs", 'systems/daggerheart/templates/sheets/parts/experience.hbs',
"systems/daggerheart/templates/sheets/parts/features.hbs", 'systems/daggerheart/templates/sheets/parts/features.hbs',
"systems/daggerheart/templates/sheets/parts/gold.hbs", 'systems/daggerheart/templates/sheets/parts/gold.hbs',
"systems/daggerheart/templates/sheets/parts/health.hbs", 'systems/daggerheart/templates/sheets/parts/health.hbs',
"systems/daggerheart/templates/sheets/parts/hope.hbs", 'systems/daggerheart/templates/sheets/parts/hope.hbs',
"systems/daggerheart/templates/sheets/parts/inventory.hbs", 'systems/daggerheart/templates/sheets/parts/inventory.hbs',
"systems/daggerheart/templates/sheets/parts/weapons.hbs", 'systems/daggerheart/templates/sheets/parts/weapons.hbs',
"systems/daggerheart/templates/sheets/parts/domainCard.hbs", 'systems/daggerheart/templates/sheets/parts/domainCard.hbs',
"systems/daggerheart/templates/sheets/parts/heritage.hbs", 'systems/daggerheart/templates/sheets/parts/heritage.hbs',
"systems/daggerheart/templates/sheets/parts/subclassFeature.hbs", 'systems/daggerheart/templates/sheets/parts/subclassFeature.hbs',
"systems/daggerheart/templates/sheets/parts/effects.hbs", 'systems/daggerheart/templates/sheets/parts/effects.hbs',
"systems/daggerheart/templates/sheets/pc/sections/inventory.hbs", 'systems/daggerheart/templates/sheets/pc/sections/inventory.hbs',
"systems/daggerheart/templates/sheets/pc/sections/loadout.hbs", 'systems/daggerheart/templates/sheets/pc/sections/loadout.hbs',
"systems/daggerheart/templates/sheets/pc/parts/heritageCard.hbs", 'systems/daggerheart/templates/sheets/pc/parts/heritageCard.hbs',
"systems/daggerheart/templates/sheets/pc/parts/advancementCard.hbs", 'systems/daggerheart/templates/sheets/pc/parts/advancementCard.hbs',
"systems/daggerheart/templates/views/parts/level.hbs", 'systems/daggerheart/templates/views/parts/level.hbs',
"systems/daggerheart/templates/components/slider.hbs", 'systems/daggerheart/templates/components/slider.hbs'
]); ]);
}; };

View file

@ -2,19 +2,14 @@
var gulp = require('gulp'); var gulp = require('gulp');
var less = require('gulp-less'); var less = require('gulp-less');
gulp.task('less', function(cb) { gulp.task('less', function (cb) {
gulp gulp.src('styles/daggerheart.less').pipe(less()).pipe(gulp.dest('styles'));
.src('styles/daggerheart.less')
.pipe(less())
.pipe(
gulp.dest("styles")
);
cb(); cb();
}); });
gulp.task( gulp.task(
'default', 'default',
gulp.series('less', function(cb) { gulp.series('less', function (cb) {
gulp.watch('styles/**/*.less', gulp.series('less')); gulp.watch('styles/**/*.less', gulp.series('less'));
cb(); cb();
}) })

View file

@ -819,7 +819,7 @@
"Bags": "Bags", "Bags": "Bags",
"Chests": "Chests" "Chests": "Chests"
}, },
"Health":{ "Health": {
"Title": "HIT POINTS & STRESS", "Title": "HIT POINTS & STRESS",
"Minor": "Minor", "Minor": "Minor",
"Major": "Major", "Major": "Major",

View file

@ -1,8 +1,7 @@
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api; const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) { export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(resolve) {
constructor(resolve){
super({}); super({});
this.resolve = resolve; this.resolve = resolve;
@ -13,17 +12,17 @@ export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(
name: '', name: '',
img: null, img: null,
customImg: 'icons/svg/mystery-man.svg', customImg: 'icons/svg/mystery-man.svg',
description: '', description: ''
}, }
}; };
} }
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
classes: ["daggerheart", "views", "ancestry-selection"], classes: ['daggerheart', 'views', 'ancestry-selection'],
position: { position: {
width: 800, width: 800,
height: "auto" height: 'auto'
}, },
actions: { actions: {
selectAncestry: this.selectAncestry, selectAncestry: this.selectAncestry,
@ -31,21 +30,21 @@ export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(
viewItem: this.viewItem, viewItem: this.viewItem,
selectImage: this.selectImage, selectImage: this.selectImage,
editImage: this._onEditImage, editImage: this._onEditImage,
saveAncestry: this.saveAncestry, saveAncestry: this.saveAncestry
}, },
form: { form: {
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false
} }
}; };
/** @override */ /** @override */
static PARTS = { static PARTS = {
damageSelection: { damageSelection: {
id: "ancestrySelection", id: 'ancestrySelection',
template: "systems/daggerheart/templates/views/ancestrySelection.hbs" template: 'systems/daggerheart/templates/views/ancestrySelection.hbs'
}
} }
};
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -57,10 +56,10 @@ export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(
_attachPartListeners(partId, htmlElement, options) { _attachPartListeners(partId, htmlElement, options) {
super._attachPartListeners(partId, htmlElement, options); super._attachPartListeners(partId, htmlElement, options);
const ancestryNameInput = $(htmlElement).find(".ancestry-name"); const ancestryNameInput = $(htmlElement).find('.ancestry-name');
if(ancestryNameInput.length > 0){ if (ancestryNameInput.length > 0) {
ancestryNameInput.on("change", this.setName.bind(this)); ancestryNameInput.on('change', this.setName.bind(this));
$(htmlElement).find(".ancestry-description").on("change", this.setDescription.bind(this)); $(htmlElement).find('.ancestry-description').on('change', this.setDescription.bind(this));
} }
// $(htmlElement).find(".ancestry-image").on("change", this.selectImage.bind(this)); // $(htmlElement).find(".ancestry-image").on("change", this.selectImage.bind(this));
} }
@ -68,19 +67,26 @@ export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(
async _prepareContext(_options) { async _prepareContext(_options) {
const systemAncestries = Array.from((await game.packs.get('daggerheart.playtest-ancestries')).index).map(x => ({ const systemAncestries = Array.from((await game.packs.get('daggerheart.playtest-ancestries')).index).map(x => ({
...x, ...x,
selected: this.data.ancestries.some(selected => selected.uuid === x.uuid), selected: this.data.ancestries.some(selected => selected.uuid === x.uuid)
})); }));
const customAncestries = game.items.reduce((acc, x) => { const customAncestries = game.items.reduce((acc, x) => {
if(x.type === 'ancestry'){ if (x.type === 'ancestry') {
acc.push({ ...x, uuid: x.uuid, selected: this.data.ancestries.some(selected => selected.uuid === x.uuid) }); acc.push({
...x,
uuid: x.uuid,
selected: this.data.ancestries.some(selected => selected.uuid === x.uuid)
});
} }
return acc; return acc;
}, []); }, []);
const ancestryFeatures = this.data.ancestries.flatMap(x => const ancestryFeatures = this.data.ancestries.flatMap(x =>
x.system.abilities.map(x => ({ ...x, selected: this.data.features.some(selected => selected.uuid === x.uuid) })) x.system.abilities.map(x => ({
...x,
selected: this.data.features.some(selected => selected.uuid === x.uuid)
}))
); );
return { return {
@ -89,13 +95,13 @@ export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(
ancestryFeatures, ancestryFeatures,
selectedAncestries: this.data.ancestries, selectedAncestries: this.data.ancestries,
selectedFeatures: this.data.features, selectedFeatures: this.data.features,
ancestryInfo: this.data.ancestryInfo, ancestryInfo: this.data.ancestryInfo
}; };
} }
static async selectAncestry(_, button) { static async selectAncestry(_, button) {
const newAncestries = [...this.data.ancestries]; const newAncestries = [...this.data.ancestries];
if(!newAncestries.findSplice(x => x.uuid === button.dataset.uuid) && this.data.ancestries.length < 2){ if (!newAncestries.findSplice(x => x.uuid === button.dataset.uuid) && this.data.ancestries.length < 2) {
const ancestry = await fromUuid(button.dataset.uuid); const ancestry = await fromUuid(button.dataset.uuid);
newAncestries.push(ancestry); newAncestries.push(ancestry);
} }
@ -108,7 +114,7 @@ export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(
static async selectFeature(_, button) { static async selectFeature(_, button) {
const newFeatures = [...this.data.features]; const newFeatures = [...this.data.features];
if(!newFeatures.findSplice(x => x.uuid === button.dataset.uuid) && this.data.features.length < 2){ if (!newFeatures.findSplice(x => x.uuid === button.dataset.uuid) && this.data.features.length < 2) {
const feature = await fromUuid(button.dataset.uuid); const feature = await fromUuid(button.dataset.uuid);
newFeatures.push(feature); newFeatures.push(feature);
} }
@ -139,7 +145,7 @@ export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(
static _onEditImage() { static _onEditImage() {
const fp = new FilePicker({ const fp = new FilePicker({
current: this.data.ancestryInfo.img, current: this.data.ancestryInfo.img,
type: "image", type: 'image',
redirectToRoot: ['icons/svg/mystery-man.svg'], redirectToRoot: ['icons/svg/mystery-man.svg'],
callback: async path => this._updateImage.bind(this)(path), callback: async path => this._updateImage.bind(this)(path),
top: this.position.top + 40, top: this.position.top + 40,
@ -148,17 +154,32 @@ export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(
return fp.browse(); return fp.browse();
} }
_updateImage(path){ _updateImage(path) {
this.data.ancestryInfo.customImg = path; this.data.ancestryInfo.customImg = path;
this.data.ancestryInfo.img = path; this.data.ancestryInfo.img = path;
this.render(true); this.render(true);
} }
static async saveAncestry(_, button) { static async saveAncestry(_, button) {
if(this.data.ancestries.length === 2){ if (this.data.ancestries.length === 2) {
const { name, img, description } = this.data.ancestryInfo; const { name, img, description } = this.data.ancestryInfo;
this.resolve({ data: { name: name, img: img, type: "ancestry", system: { description: description, abilities: this.data.features.map(x => ({ name: x.name, img: x.img, uuid: x.uuid, subclassLevel: '' })) }}}); this.resolve({
data: {
name: name,
img: img,
type: 'ancestry',
system: {
description: description,
abilities: this.data.features.map(x => ({
name: x.name,
img: x.img,
uuid: x.uuid,
subclassLevel: ''
}))
}
}
});
} else { } else {
this.resolve({ data: this.data.ancestries[0].toObject() }); this.resolve({ data: this.data.ancestries[0].toObject() });
} }

View file

@ -1,6 +1,6 @@
export default class DhpChatMesssage extends ChatMessage { export default class DhpChatMesssage extends ChatMessage {
async renderHTML() { async renderHTML() {
if(this.type === 'dualityRoll' || this.type === 'adversaryRoll' || this.type === 'abilityUse'){ if (this.type === 'dualityRoll' || this.type === 'adversaryRoll' || this.type === 'abilityUse') {
this.content = await foundry.applications.handlebars.renderTemplate(this.content, this.system); this.content = await foundry.applications.handlebars.renderTemplate(this.content, this.system);
} }

View file

@ -1,8 +1,8 @@
import DaggerheartSheet from '../sheets/daggerheart-sheet.mjs'; import DaggerheartSheet from '../sheets/daggerheart-sheet.mjs';
const {ApplicationV2} = foundry.applications.api; const { ApplicationV2 } = foundry.applications.api;
export default class DaggerheartActionConfig extends DaggerheartSheet(ApplicationV2) { export default class DaggerheartActionConfig extends DaggerheartSheet(ApplicationV2) {
constructor(action){ constructor(action) {
super({}); super({});
this.action = action; this.action = action;
@ -15,35 +15,42 @@ export default class DaggerheartActionConfig extends DaggerheartSheet(Applicatio
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: "daggerheart-action", id: 'daggerheart-action',
classes: ["daggerheart", "views", "action"], classes: ['daggerheart', 'views', 'action'],
position: { width: 600, height: 'auto' }, position: { width: 600, height: 'auto' },
actions: { actions: {
toggleSection: this.toggleSection, toggleSection: this.toggleSection
}, },
form: { form: {
handler: this.updateForm, handler: this.updateForm,
closeOnSubmit: true, closeOnSubmit: true
}, }
}; };
static PARTS = { static PARTS = {
form: { form: {
id: "action", id: 'action',
template: "systems/daggerheart/templates/views/action.hbs" template: 'systems/daggerheart/templates/views/action.hbs'
}
} }
};
_getTabs() { _getTabs() {
const tabs = { const tabs = {
effects: { active: true, cssClass: '', group: 'primary', id: 'effects', icon: null, label: 'Effects' }, effects: { active: true, cssClass: '', group: 'primary', id: 'effects', icon: null, label: 'Effects' },
useage: { active: false, cssClass: '', group: 'primary', id: 'useage', icon: null, label: 'Useage' }, useage: { active: false, cssClass: '', group: 'primary', id: 'useage', icon: null, label: 'Useage' },
conditions: { active: false, cssClass: '', group: 'primary', id: 'conditions', icon: null, label: 'Conditions' }, conditions: {
active: false,
cssClass: '',
group: 'primary',
id: 'conditions',
icon: null,
label: 'Conditions'
} }
};
for ( const v of Object.values(tabs) ) { for (const v of Object.values(tabs)) {
v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active; v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active;
v.cssClass = v.active ? "active" : ""; v.cssClass = v.active ? 'active' : '';
} }
return tabs; return tabs;
@ -65,10 +72,10 @@ export default class DaggerheartActionConfig extends DaggerheartSheet(Applicatio
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
const data = foundry.utils.expandObject(foundry.utils.mergeObject(this.action.toObject(), formData.object)); const data = foundry.utils.expandObject(foundry.utils.mergeObject(this.action.toObject(), formData.object));
const newActions = this.action.parent.actions.map(x => x.toObject()); const newActions = this.action.parent.actions.map(x => x.toObject());
if(!newActions.findSplice(x => x.id === data.id, data)){ if (!newActions.findSplice(x => x.id === data.id, data)) {
newActions.push(data); newActions.push(data);
} }
await this.action.parent.parent.update({ "system.actions": newActions }); await this.action.parent.parent.update({ 'system.actions': newActions });
} }
} }

View file

@ -1,13 +1,13 @@
export default function DhpApplicationMixin(Base) { export default function DhpApplicationMixin(Base) {
return class DhpSheet extends Base { return class DhpSheet extends Base {
static applicationType = "sheets"; static applicationType = 'sheets';
static documentType = ""; static documentType = '';
static get defaultOptions() { static get defaultOptions() {
return Object.assign(super.defaultOptions, { return Object.assign(super.defaultOptions, {
classes: ["daggerheart", "sheet", this.documentType], classes: ['daggerheart', 'sheet', this.documentType],
template: `systems/${SYSTEM.id}/templates/${this.applicationType}/${this.documentType}.hbs`, template: `systems/${SYSTEM.id}/templates/${this.applicationType}/${this.documentType}.hbs`,
height: "auto", height: 'auto',
submitOnChange: true, submitOnChange: true,
submitOnClose: false, submitOnClose: false,
width: 450 width: 450
@ -16,7 +16,7 @@ export default function DhpApplicationMixin(Base) {
/** @override */ /** @override */
get title() { get title() {
const {documentName, type, name} = this.object; const { documentName, type, name } = this.object;
// const typeLabel = game.i18n.localize(CONFIG[documentName].typeLabels[type]); // const typeLabel = game.i18n.localize(CONFIG[documentName].typeLabels[type]);
const typeLabel = documentName; const typeLabel = documentName;
return `[${typeLabel}] ${name}`; return `[${typeLabel}] ${name}`;
@ -32,7 +32,7 @@ export default function DhpApplicationMixin(Base) {
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
html.on("click", "[data-action]", this.#onClickAction.bind(this)); html.on('click', '[data-action]', this.#onClickAction.bind(this));
} }
async #onClickAction(event) { async #onClickAction(event) {
@ -44,5 +44,5 @@ export default function DhpApplicationMixin(Base) {
} }
async _handleAction(action, event, button) {} async _handleAction(action, event, button) {}
} };
} }

View file

@ -1,53 +1,52 @@
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api; const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
export default class DamageSelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) { export default class DamageSelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(rollString, bonusDamage, hope, resolve) {
constructor(rollString, bonusDamage, hope, resolve){
super({}); super({});
this.data = { this.data = {
rollString, rollString,
bonusDamage: bonusDamage.reduce((acc, x) => { bonusDamage: bonusDamage.reduce((acc, x) => {
if(x.appliesOn === SYSTEM.EFFECTS.applyLocations.damageRoll.id){ if (x.appliesOn === SYSTEM.EFFECTS.applyLocations.damageRoll.id) {
acc.push(({ acc.push({
...x, ...x,
hopeUses: 0 hopeUses: 0
})); });
} }
return acc; return acc;
}, []), }, []),
hope, hope
} };
this.resolve = resolve; this.resolve = resolve;
} }
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
classes: ["daggerheart", "views", "damage-selection"], classes: ['daggerheart', 'views', 'damage-selection'],
position: { position: {
width: 400, width: 400,
height: "auto" height: 'auto'
}, },
actions: { actions: {
decreaseHopeUse: this.decreaseHopeUse, decreaseHopeUse: this.decreaseHopeUse,
increaseHopeUse: this.increaseHopeUse, increaseHopeUse: this.increaseHopeUse,
rollDamage: this.rollDamage, rollDamage: this.rollDamage
}, },
form: { form: {
handler: this.updateSelection, handler: this.updateSelection,
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false
} }
}; };
/** @override */ /** @override */
static PARTS = { static PARTS = {
damageSelection: { damageSelection: {
id: "damageSelection", id: 'damageSelection',
template: "systems/daggerheart/templates/views/damageSelection.hbs" template: 'systems/daggerheart/templates/views/damageSelection.hbs'
}
} }
};
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -60,19 +59,19 @@ export default class DamageSelectionDialog extends HandlebarsApplicationMixin(Ap
return { return {
rollString: this.getRollString(), rollString: this.getRollString(),
bonusDamage: this.data.bonusDamage, bonusDamage: this.data.bonusDamage,
hope: this.data.hope+1, hope: this.data.hope + 1,
hopeUsed: this.getHopeUsed(), hopeUsed: this.getHopeUsed()
} };
} }
static updateSelection(event, _, formData){ static updateSelection(event, _, formData) {
const { bonusDamage, ...rest } = foundry.utils.expandObject(formData.object); const { bonusDamage, ...rest } = foundry.utils.expandObject(formData.object);
for(var index in bonusDamage){ for (var index in bonusDamage) {
this.data.bonusDamage[index].initiallySelected = bonusDamage[index].initiallySelected; this.data.bonusDamage[index].initiallySelected = bonusDamage[index].initiallySelected;
if(bonusDamage[index].hopeUses){ if (bonusDamage[index].hopeUses) {
const value = Number.parseInt(bonusDamage[index].hopeUses); const value = Number.parseInt(bonusDamage[index].hopeUses);
if(!Number.isNaN(value)) this.data.bonusDamage[index].hopeUses = value; if (!Number.isNaN(value)) this.data.bonusDamage[index].hopeUses = value;
} }
} }
@ -80,40 +79,46 @@ export default class DamageSelectionDialog extends HandlebarsApplicationMixin(Ap
this.render(true); this.render(true);
} }
getRollString(){ getRollString() {
return this.data.rollString.concat(this.data.bonusDamage.reduce((acc, x) => { return this.data.rollString.concat(
if(x.initiallySelected){ this.data.bonusDamage.reduce((acc, x) => {
const nr = 1+x.hopeUses; if (x.initiallySelected) {
const nr = 1 + x.hopeUses;
const baseDamage = x.value; const baseDamage = x.value;
return acc.concat(` + ${nr}${baseDamage}`); return acc.concat(` + ${nr}${baseDamage}`);
} }
return acc; return acc;
}, "")); }, '')
);
} }
getHopeUsed(){ getHopeUsed() {
return this.data.bonusDamage.reduce((acc, x) => acc+x.hopeUses, 0); return this.data.bonusDamage.reduce((acc, x) => acc + x.hopeUses, 0);
} }
static decreaseHopeUse(_, button){ static decreaseHopeUse(_, button) {
const index = Number.parseInt(button.dataset.index); const index = Number.parseInt(button.dataset.index);
if(this.data.bonusDamage[index].hopeUses - 1 >= 0) { if (this.data.bonusDamage[index].hopeUses - 1 >= 0) {
this.data.bonusDamage[index].hopeUses -= 1; this.data.bonusDamage[index].hopeUses -= 1;
this.render(true); this.render(true);
} }
} }
static increaseHopeUse(_, button){ static increaseHopeUse(_, button) {
const index = Number.parseInt(button.dataset.index); const index = Number.parseInt(button.dataset.index);
if(this.data.bonusDamage[index].hopeUses <= this.data.hope+1) { if (this.data.bonusDamage[index].hopeUses <= this.data.hope + 1) {
this.data.bonusDamage[index].hopeUses += 1; this.data.bonusDamage[index].hopeUses += 1;
this.render(true); this.render(true);
} }
} }
static rollDamage(){ static rollDamage() {
this.resolve({ rollString: this.getRollString(), bonusDamage: this.data.bonusDamage, hopeUsed: this.getHopeUsed() }); this.resolve({
rollString: this.getRollString(),
bonusDamage: this.data.bonusDamage,
hopeUsed: this.getHopeUsed()
});
this.close(); this.close();
} }
} }

View file

@ -1,32 +1,32 @@
const {HandlebarsApplicationMixin, ApplicationV2} = foundry.applications.api; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
export default class DhpDeathMove extends HandlebarsApplicationMixin(ApplicationV2) { export default class DhpDeathMove extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(actor){ constructor(actor) {
super({}); super({});
this.actor = actor; this.actor = actor;
this.selectedMove = null; this.selectedMove = null;
} }
get title(){ get title() {
return game.i18n.format("DAGGERHEART.Application.DeathMove.Title", { actor: this.actor.name }); return game.i18n.format('DAGGERHEART.Application.DeathMove.Title', { actor: this.actor.name });
} }
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
classes: ["daggerheart", "views", "death-move"], classes: ['daggerheart', 'views', 'death-move'],
position: { width: 800, height: 'auto' }, position: { width: 800, height: 'auto' },
actions: { actions: {
selectMove: this.selectMove, selectMove: this.selectMove,
takeMove: this.takeMove, takeMove: this.takeMove
}, }
}; };
static PARTS = { static PARTS = {
application: { application: {
id: "death-move", id: 'death-move',
template: "systems/daggerheart/templates/views/deathMove.hbs" template: 'systems/daggerheart/templates/views/deathMove.hbs'
}
} }
};
async _prepareContext(_options) { async _prepareContext(_options) {
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
@ -36,24 +36,23 @@ export default class DhpDeathMove extends HandlebarsApplicationMixin(Application
return context; return context;
} }
static selectMove(_, button) {
static selectMove(_, button){
const move = button.dataset.move; const move = button.dataset.move;
this.selectedMove = SYSTEM.GENERAL.deathMoves[move]; this.selectedMove = SYSTEM.GENERAL.deathMoves[move];
this.render(); this.render();
} }
static async takeMove(){ static async takeMove() {
const cls = getDocumentClass("ChatMessage"); const cls = getDocumentClass('ChatMessage');
const msg = new cls({ const msg = new cls({
user: game.user.id, user: game.user.id,
content: await renderTemplate("systems/daggerheart/templates/chat/deathMove.hbs", { content: await renderTemplate('systems/daggerheart/templates/chat/deathMove.hbs', {
player: game.user.character.name, player: game.user.character.name,
title: game.i18n.localize(this.selectedMove.name), title: game.i18n.localize(this.selectedMove.name),
img: this.selectedMove.img, img: this.selectedMove.img,
description: game.i18n.localize(this.selectedMove.description), description: game.i18n.localize(this.selectedMove.description)
}), })
}); });
cls.create(msg.toObject()); cls.create(msg.toObject());

View file

@ -1,7 +1,7 @@
const {HandlebarsApplicationMixin, ApplicationV2} = foundry.applications.api; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV2) { export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(actor, shortrest){ constructor(actor, shortrest) {
super({}); super({});
this.actor = actor; this.actor = actor;
@ -11,27 +11,27 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
this.customActivity = SYSTEM.GENERAL.downtime.custom; this.customActivity = SYSTEM.GENERAL.downtime.custom;
} }
get title(){ get title() {
return `${this.actor.name} - ${this.shortrest ? 'Short Rest': 'Long Rest'}`; return `${this.actor.name} - ${this.shortrest ? 'Short Rest' : 'Long Rest'}`;
} }
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
classes: ["daggerheart", "views", "downtime"], classes: ['daggerheart', 'views', 'downtime'],
position: { width: 800, height: 'auto' }, position: { width: 800, height: 'auto' },
actions: { actions: {
selectActivity: this.selectActivity, selectActivity: this.selectActivity,
takeDowntime: this.takeDowntime, takeDowntime: this.takeDowntime
}, },
form: { handler: this.updateData, submitOnChange: true } form: { handler: this.updateData, submitOnChange: true }
}; };
static PARTS = { static PARTS = {
application: { application: {
id: "downtime", id: 'downtime',
template: "systems/daggerheart/templates/views/downtime.hbs" template: 'systems/daggerheart/templates/views/downtime.hbs'
}
} }
};
async _prepareContext(_options) { async _prepareContext(_options) {
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
@ -39,35 +39,44 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
context.options = this.shortrest ? SYSTEM.GENERAL.downtime.shortRest : SYSTEM.GENERAL.downtime.longRest; context.options = this.shortrest ? SYSTEM.GENERAL.downtime.shortRest : SYSTEM.GENERAL.downtime.longRest;
context.customActivity = this.customActivity; context.customActivity = this.customActivity;
context.disabledDowntime = !this.selectedActivity || (this.selectedActivity.id === this.customActivity.id && (!this.customActivity.name || !this.customActivity.description)); context.disabledDowntime =
!this.selectedActivity ||
(this.selectedActivity.id === this.customActivity.id &&
(!this.customActivity.name || !this.customActivity.description));
return context; return context;
} }
static selectActivity(_, button) {
static selectActivity(_, button){
const activity = button.dataset.activity; const activity = button.dataset.activity;
this.selectedActivity = activity === this.customActivity.id ? this.customActivity : this.shortrest ? SYSTEM.GENERAL.downtime.shortRest[activity] : SYSTEM.GENERAL.downtime.longRest[activity]; this.selectedActivity =
activity === this.customActivity.id
? this.customActivity
: this.shortrest
? SYSTEM.GENERAL.downtime.shortRest[activity]
: SYSTEM.GENERAL.downtime.longRest[activity];
this.render(); this.render();
} }
static async takeDowntime(){ static async takeDowntime() {
const refreshedFeatures = this.shortrest ? this.actor.system.refreshableFeatures.shortRest : [...this.actor.system.refreshableFeatures.shortRest, ...this.actor.system.refreshableFeatures.longRest]; const refreshedFeatures = this.shortrest
for(var feature of refreshedFeatures){ ? this.actor.system.refreshableFeatures.shortRest
: [...this.actor.system.refreshableFeatures.shortRest, ...this.actor.system.refreshableFeatures.longRest];
for (var feature of refreshedFeatures) {
await feature.system.refresh(); await feature.system.refresh();
} }
const cls = getDocumentClass("ChatMessage"); const cls = getDocumentClass('ChatMessage');
const msg = new cls({ const msg = new cls({
user: game.user.id, user: game.user.id,
content: await renderTemplate("systems/daggerheart/templates/chat/downtime.hbs", { content: await renderTemplate('systems/daggerheart/templates/chat/downtime.hbs', {
player: game.user.character.name, player: game.user.character.name,
title: game.i18n.localize(this.selectedActivity.name), title: game.i18n.localize(this.selectedActivity.name),
img: this.selectedActivity.img, img: this.selectedActivity.img,
description: game.i18n.localize(this.selectedActivity.description), description: game.i18n.localize(this.selectedActivity.description),
refreshedFeatures: refreshedFeatures, refreshedFeatures: refreshedFeatures
}), })
}); });
cls.create(msg.toObject()); cls.create(msg.toObject());
@ -75,7 +84,7 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
this.close(); this.close();
} }
static async updateData(event, element, formData){ static async updateData(event, element, formData) {
this.customActivity = foundry.utils.mergeObject(this.customActivity, formData.object); this.customActivity = foundry.utils.mergeObject(this.customActivity, formData.object);
this.render(); this.render();
} }

View file

@ -1,60 +1,63 @@
import SelectDialog from "../dialogs/selectDialog.mjs"; import SelectDialog from '../dialogs/selectDialog.mjs';
import { getTier } from "../helpers/utils.mjs"; import { getTier } from '../helpers/utils.mjs';
import DhpMulticlassDialog from "./multiclassDialog.mjs"; import DhpMulticlassDialog from './multiclassDialog.mjs';
const {HandlebarsApplicationMixin, ApplicationV2} = foundry.applications.api; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
export default class DhpLevelup extends HandlebarsApplicationMixin(ApplicationV2) { export default class DhpLevelup extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(actor){ constructor(actor) {
super({}); super({});
this.actor = actor; this.actor = actor;
this.data = foundry.utils.deepClone(actor.system.levelData); this.data = foundry.utils.deepClone(actor.system.levelData);
this.activeLevel = actor.system.levelData.currentLevel+1; this.activeLevel = actor.system.levelData.currentLevel + 1;
} }
get title(){ get title() {
return `${this.actor.name} - Level Up`; return `${this.actor.name} - Level Up`;
} }
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
id: "daggerheart-levelup", id: 'daggerheart-levelup',
classes: ["daggerheart", "views", "levelup"], classes: ['daggerheart', 'views', 'levelup'],
position: { width: 1200, height: 'auto' }, position: { width: 1200, height: 'auto' },
window: { window: {
resizable: true, resizable: true
}, },
actions: { actions: {
toggleBox: this.toggleBox, toggleBox: this.toggleBox,
advanceLevel: this.advanceLevel, advanceLevel: this.advanceLevel,
finishLevelup: this.finishLevelup, finishLevelup: this.finishLevelup
}, }
}; };
static PARTS = { static PARTS = {
form: { form: {
id: "levelup", id: 'levelup',
template: "systems/daggerheart/templates/views/levelup.hbs" template: 'systems/daggerheart/templates/views/levelup.hbs'
}
} }
};
async _prepareContext(_options) { async _prepareContext(_options) {
let selectedChoices = 0, multiclassing = {}, subclassing = {}; let selectedChoices = 0,
const leveledTiers = Object.keys(this.data.levelups).reduce((acc, levelKey) => { multiclassing = {},
subclassing = {};
const leveledTiers = Object.keys(this.data.levelups).reduce(
(acc, levelKey) => {
const levelData = this.data.levelups[levelKey]; const levelData = this.data.levelups[levelKey];
['tier1','tier2','tier3'].forEach(tierKey => { ['tier1', 'tier2', 'tier3'].forEach(tierKey => {
let tierUpdate = {}; let tierUpdate = {};
const tierData = levelData[tierKey]; const tierData = levelData[tierKey];
if(tierData){ if (tierData) {
tierUpdate = Object.keys(tierData).reduce((acc, propertyKey) => { tierUpdate = Object.keys(tierData).reduce((acc, propertyKey) => {
const values = tierData[propertyKey]; const values = tierData[propertyKey];
const level = Number.parseInt(levelKey); const level = Number.parseInt(levelKey);
acc[propertyKey] = Object.values(values).map(value => { acc[propertyKey] = Object.values(values).map(value => {
if(value && level === this.activeLevel) selectedChoices++; if (value && level === this.activeLevel) selectedChoices++;
if(propertyKey === 'multiclass') multiclassing[levelKey] = true; if (propertyKey === 'multiclass') multiclassing[levelKey] = true;
if(propertyKey === 'subclass') subclassing[tierKey] = true; if (propertyKey === 'subclass') subclassing[tierKey] = true;
return { level: level, value: value }; return { level: level, value: value };
}); });
@ -65,13 +68,15 @@ export default class DhpLevelup extends HandlebarsApplicationMixin(ApplicationV2
Object.keys(tierUpdate).forEach(propertyKey => { Object.keys(tierUpdate).forEach(propertyKey => {
const property = tierUpdate[propertyKey]; const property = tierUpdate[propertyKey];
const propertyValues = foundry.utils.getProperty(acc, `${tierKey}.${propertyKey}`)??[]; const propertyValues = foundry.utils.getProperty(acc, `${tierKey}.${propertyKey}`) ?? [];
foundry.utils.setProperty(acc, `${tierKey}.${propertyKey}`, [...propertyValues, ...property]); foundry.utils.setProperty(acc, `${tierKey}.${propertyKey}`, [...propertyValues, ...property]);
}); });
}); });
return acc; return acc;
}, { tier1: {}, tier2: {}, tier3: {} }); },
{ tier1: {}, tier2: {}, tier3: {} }
);
const activeTier = getTier(this.activeLevel); const activeTier = getTier(this.activeLevel);
const data = Object.keys(SYSTEM.ACTOR.levelupData).reduce((acc, tierKey) => { const data = Object.keys(SYSTEM.ACTOR.levelupData).reduce((acc, tierKey) => {
@ -85,21 +90,35 @@ export default class DhpLevelup extends HandlebarsApplicationMixin(ApplicationV2
choices: Object.keys(tier.choices).reduce((acc, propertyKey) => { choices: Object.keys(tier.choices).reduce((acc, propertyKey) => {
const property = tier.choices[propertyKey]; const property = tier.choices[propertyKey];
acc[propertyKey] = { description: property.description, cost: property.cost ?? 1, values: [] }; acc[propertyKey] = { description: property.description, cost: property.cost ?? 1, values: [] };
for(var i = 0; i < property.maxChoices; i++){ for (var i = 0; i < property.maxChoices; i++) {
const leveledValue = leveledTiers[tierKey][propertyKey]?.[i]; const leveledValue = leveledTiers[tierKey][propertyKey]?.[i];
const subclassLock = propertyKey === 'subclass' && Object.keys(multiclassing).find(x => getTier(Number.parseInt(x)) === tierKey); const subclassLock =
propertyKey === 'subclass' &&
Object.keys(multiclassing).find(x => getTier(Number.parseInt(x)) === tierKey);
const subclassMulticlassLock = propertyKey === 'multiclass' && subclassing[tierKey]; const subclassMulticlassLock = propertyKey === 'multiclass' && subclassing[tierKey];
const multiclassLock = propertyKey === 'multiclass' && Object.keys(multiclassing).length > 0 && !(leveledValue && Object.keys(multiclassing).find(x => Number.parseInt(x) === leveledValue.level)); const multiclassLock =
const locked = leveledValue && leveledValue.level !== this.activeLevel || subclassLock || subclassMulticlassLock || multiclassLock; propertyKey === 'multiclass' &&
const disabled = tierKey > activeTier || (selectedChoices === 2 && !(leveledValue && leveledValue.level === this.activeLevel)) || locked; Object.keys(multiclassing).length > 0 &&
!(
leveledValue &&
Object.keys(multiclassing).find(x => Number.parseInt(x) === leveledValue.level)
);
const locked =
(leveledValue && leveledValue.level !== this.activeLevel) ||
subclassLock ||
subclassMulticlassLock ||
multiclassLock;
const disabled =
tierKey > activeTier ||
(selectedChoices === 2 && !(leveledValue && leveledValue.level === this.activeLevel)) ||
locked;
acc[propertyKey].values.push({ acc[propertyKey].values.push({
selected: leveledValue?.value !== undefined, selected: leveledValue?.value !== undefined,
path: `levelups.${this.activeLevel}.${tierKey}.${propertyKey}.${i}`, path: `levelups.${this.activeLevel}.${tierKey}.${propertyKey}.${i}`,
description: game.i18n.localize(property.description), description: game.i18n.localize(property.description),
disabled: disabled, disabled: disabled,
locked: locked, locked: locked
}); });
} }
@ -114,70 +133,122 @@ export default class DhpLevelup extends HandlebarsApplicationMixin(ApplicationV2
data: data, data: data,
activeLevel: this.activeLevel, activeLevel: this.activeLevel,
changedLevel: this.actor.system.levelData.changedLevel, changedLevel: this.actor.system.levelData.changedLevel,
completedSelection: selectedChoices === 2, completedSelection: selectedChoices === 2
} };
} }
static async toggleBox(_, button){ static async toggleBox(_, button) {
const path = button.dataset.path; const path = button.dataset.path;
if(foundry.utils.getProperty(this.data, path)){ if (foundry.utils.getProperty(this.data, path)) {
const pathParts = path.split('.'); const pathParts = path.split('.');
const arrayPart = pathParts.slice(0, pathParts.length-1).join('.'); const arrayPart = pathParts.slice(0, pathParts.length - 1).join('.');
let array = foundry.utils.getProperty(this.data, arrayPart); let array = foundry.utils.getProperty(this.data, arrayPart);
if(button.dataset.levelAttribute === 'multiclass'){ if (button.dataset.levelAttribute === 'multiclass') {
array = []; array = [];
} } else {
else { delete array[Number.parseInt(pathParts[pathParts.length - 1])];
delete array[Number.parseInt(pathParts[pathParts.length-1])];
} }
foundry.utils.setProperty(this.data, arrayPart, array); foundry.utils.setProperty(this.data, arrayPart, array);
} else { } else {
const updates = [{ path: path, value: { level: this.activeLevel } }]; const updates = [{ path: path, value: { level: this.activeLevel } }];
const levelChoices = SYSTEM.ACTOR.levelChoices[button.dataset.levelAttribute]; const levelChoices = SYSTEM.ACTOR.levelChoices[button.dataset.levelAttribute];
if(button.dataset.levelAttribute === 'subclass'){ if (button.dataset.levelAttribute === 'subclass') {
if(!this.actor.system.multiclassSubclass){ if (!this.actor.system.multiclassSubclass) {
updates[0].value.value = { multiclass: false, feature: this.actor.system.subclass.system.specializationFeature.unlocked ? 'mastery' : 'specialization' }; updates[0].value.value = {
multiclass: false,
feature: this.actor.system.subclass.system.specializationFeature.unlocked
? 'mastery'
: 'specialization'
};
} else {
const choices = [
{ name: this.actor.system.subclass.name, value: this.actor.system.subclass.uuid },
{
name: this.actor.system.multiclassSubclass.name,
value: this.actor.system.multiclassSubclass.uuid
} }
else { ];
const choices = [{name: this.actor.system.subclass.name, value: this.actor.system.subclass.uuid}, {name: this.actor.system.multiclassSubclass.name, value: this.actor.system.multiclassSubclass.uuid}]; const indexes = await SelectDialog.selectItem({
const indexes = await SelectDialog.selectItem({ actor: this.actor, choices: choices, title: levelChoices.title, nrChoices: 1 }); actor: this.actor,
if(indexes.length === 0) { choices: choices,
title: levelChoices.title,
nrChoices: 1
});
if (indexes.length === 0) {
this.render(); this.render();
return; return;
} }
const multiclassSubclass = choices[indexes[0]].name === this.actor.system.multiclassSubclass.name; const multiclassSubclass = choices[indexes[0]].name === this.actor.system.multiclassSubclass.name;
updates[0].value.value = { multiclass: multiclassSubclass, feature: this.actor.system.multiclassSubclass.system.specializationFeature.unlocked ? 'mastery' : 'specialization' }; updates[0].value.value = {
multiclass: multiclassSubclass,
feature: this.actor.system.multiclassSubclass.system.specializationFeature.unlocked
? 'mastery'
: 'specialization'
};
} }
} } else if (button.dataset.levelAttribute === 'multiclass') {
else if (button.dataset.levelAttribute === 'multiclass'){ const multiclassAwait = new Promise(resolve => {
const multiclassAwait = new Promise((resolve) => {
new DhpMulticlassDialog(this.actor.name, this.actor.system.class, resolve).render(true); new DhpMulticlassDialog(this.actor.name, this.actor.system.class, resolve).render(true);
}); });
const multiclassData = await multiclassAwait; const multiclassData = await multiclassAwait;
if(!multiclassData) { if (!multiclassData) {
this.render(); this.render();
return; return;
} }
const pathParts = path.split('.'); const pathParts = path.split('.');
const arrayPart = pathParts.slice(0, pathParts.length-1).join('.'); const arrayPart = pathParts.slice(0, pathParts.length - 1).join('.');
updates[0] = { path: [arrayPart, '0'].join('.'), value: { level: this.activeLevel, value: { class: multiclassData.class, subclass: multiclassData.subclass, domain: multiclassData.domain, level: this.activeLevel } } }; updates[0] = {
updates[1] = { path: [arrayPart, '1'].join('.'), value: { level: this.activeLevel, value: { class: multiclassData.class, subclass: multiclassData.subclass, domain: multiclassData.domain, level: this.activeLevel } } }; path: [arrayPart, '0'].join('.'),
value: {
level: this.activeLevel,
value: {
class: multiclassData.class,
subclass: multiclassData.subclass,
domain: multiclassData.domain,
level: this.activeLevel
} }
else { }
if(levelChoices.choices.length > 0){ };
if(typeof levelChoices.choices === 'string'){ updates[1] = {
const choices = foundry.utils.getProperty(this.actor, levelChoices.choices).map(x => ({ name: x.description, value: x.id })); path: [arrayPart, '1'].join('.'),
const indexes = await SelectDialog.selectItem({ actor: this.actor, choices: choices, title: levelChoices.title, nrChoices: levelChoices.nrChoices }); value: {
if(indexes.length === 0) { level: this.activeLevel,
value: {
class: multiclassData.class,
subclass: multiclassData.subclass,
domain: multiclassData.domain,
level: this.activeLevel
}
}
};
} else {
if (levelChoices.choices.length > 0) {
if (typeof levelChoices.choices === 'string') {
const choices = foundry.utils
.getProperty(this.actor, levelChoices.choices)
.map(x => ({ name: x.description, value: x.id }));
const indexes = await SelectDialog.selectItem({
actor: this.actor,
choices: choices,
title: levelChoices.title,
nrChoices: levelChoices.nrChoices
});
if (indexes.length === 0) {
this.render(); this.render();
return; return;
} }
updates[0].value.value = choices.filter((_, index) => indexes.includes(index)).map(x => x.value); updates[0].value.value = choices
} .filter((_, index) => indexes.includes(index))
else { .map(x => x.value);
const indexes = await SelectDialog.selectItem({ actor: this.actor, choices: levelChoices.choices, title: levelChoices.title, nrChoices: levelChoices.nrChoices }); } else {
if(indexes.length === 0) { const indexes = await SelectDialog.selectItem({
actor: this.actor,
choices: levelChoices.choices,
title: levelChoices.title,
nrChoices: levelChoices.nrChoices
});
if (indexes.length === 0) {
this.render(); this.render();
return; return;
} }
@ -198,44 +269,57 @@ export default class DhpLevelup extends HandlebarsApplicationMixin(ApplicationV2
this.render(); this.render();
} }
static advanceLevel(){ static advanceLevel() {
this.activeLevel += 1; this.activeLevel += 1;
this.render(); this.render();
} }
static async finishLevelup(){ static async finishLevelup() {
this.data.currentLevel = this.data.changedLevel; this.data.currentLevel = this.data.changedLevel;
let multiclass = null; let multiclass = null;
for(var level in this.data.levelups){ for (var level in this.data.levelups) {
for(var tier in this.data.levelups[level]){ for (var tier in this.data.levelups[level]) {
for(var category in this.data.levelups[level][tier]) { for (var category in this.data.levelups[level][tier]) {
for (var value in this.data.levelups[level][tier][category]){ for (var value in this.data.levelups[level][tier][category]) {
if(category === 'multiclass'){ if (category === 'multiclass') {
multiclass = this.data.levelups[level][tier][category][value].value; multiclass = this.data.levelups[level][tier][category][value].value;
this.data.levelups[level][tier][category][value] = true; this.data.levelups[level][tier][category][value] = true;
} else { } else {
this.data.levelups[level][tier][category][value] = this.data.levelups[level][tier][category][value].value ?? true; this.data.levelups[level][tier][category][value] =
this.data.levelups[level][tier][category][value].value ?? true;
} }
} }
} }
} }
} }
const tiersMoved = getTier(this.actor.system.levelData.changedLevel, true) - getTier(this.actor.system.levelData.currentLevel, true); const tiersMoved =
const experiences = Array.from(Array(tiersMoved), (_,index) => ({ id: foundry.utils.randomID(), level: this.actor.system.experiences.length+index*3, description: '', value: 1 })); getTier(this.actor.system.levelData.changedLevel, true) -
getTier(this.actor.system.levelData.currentLevel, true);
const experiences = Array.from(Array(tiersMoved), (_, index) => ({
id: foundry.utils.randomID(),
level: this.actor.system.experiences.length + index * 3,
description: '',
value: 1
}));
await this.actor.update({ system: { await this.actor.update(
{
system: {
levelData: this.data, levelData: this.data,
experiences: [...this.actor.system.experiences, ...experiences], experiences: [...this.actor.system.experiences, ...experiences]
}}, { diff: false }); }
},
{ diff: false }
);
if(!this.actor.multiclass && multiclass){ if (!this.actor.multiclass && multiclass) {
const multiclassClass = (await fromUuid(multiclass.class.uuid)).toObject(); const multiclassClass = (await fromUuid(multiclass.class.uuid)).toObject();
multiclassClass.system.domains = [multiclass.domain.id]; multiclassClass.system.domains = [multiclass.domain.id];
multiclassClass.system.multiclass = multiclass.level; multiclassClass.system.multiclass = multiclass.level;
const multiclassFeatures = []; const multiclassFeatures = [];
for(var i = 0; i < multiclassClass.system.features.length; i++){ for (var i = 0; i < multiclassClass.system.features.length; i++) {
const feature = (await fromUuid(multiclassClass.system.features[i].uuid)).toObject(); const feature = (await fromUuid(multiclassClass.system.features[i].uuid)).toObject();
feature.system.multiclass = multiclass.level; feature.system.multiclass = multiclass.level;
multiclassFeatures.push(feature); multiclassFeatures.push(feature);
@ -245,15 +329,19 @@ export default class DhpLevelup extends HandlebarsApplicationMixin(ApplicationV2
multiclassSubclass.system.multiclass = multiclass.level; multiclassSubclass.system.multiclass = multiclass.level;
const multiclassSubclassFeatures = {}; const multiclassSubclassFeatures = {};
const features = [multiclassSubclass.system.foundationFeature, multiclassSubclass.system.specializationFeature, multiclassSubclass.system.masteryFeature]; const features = [
for(var i = 0; i < features.length; i++){ multiclassSubclass.system.foundationFeature,
multiclassSubclass.system.specializationFeature,
multiclassSubclass.system.masteryFeature
];
for (var i = 0; i < features.length; i++) {
const path = i === 0 ? 'foundationFeature' : i === 1 ? 'specializationFeature' : 'masteryFeature'; const path = i === 0 ? 'foundationFeature' : i === 1 ? 'specializationFeature' : 'masteryFeature';
const feature = features[i]; const feature = features[i];
for(var ability of feature.abilities){ for (var ability of feature.abilities) {
const data = (await fromUuid(ability.uuid)).toObject(); const data = (await fromUuid(ability.uuid)).toObject();
if(i > 0 ) data.system.disabled = true; if (i > 0) data.system.disabled = true;
data.system.multiclass = multiclass.level; data.system.multiclass = multiclass.level;
if(!multiclassSubclassFeatures[path]) multiclassSubclassFeatures[path] = [data]; if (!multiclassSubclassFeatures[path]) multiclassSubclassFeatures[path] = [data];
else multiclassSubclassFeatures[path].push(data); else multiclassSubclassFeatures[path].push(data);
// data.uuid = feature.uuid; // data.uuid = feature.uuid;
@ -264,18 +352,21 @@ export default class DhpLevelup extends HandlebarsApplicationMixin(ApplicationV2
} }
} }
for(let subclassFeaturesKey in multiclassSubclassFeatures){ for (let subclassFeaturesKey in multiclassSubclassFeatures) {
const values = multiclassSubclassFeatures[subclassFeaturesKey]; const values = multiclassSubclassFeatures[subclassFeaturesKey];
const abilityResults = await this.actor.createEmbeddedDocuments('Item', values); const abilityResults = await this.actor.createEmbeddedDocuments('Item', values);
for(var i = 0; i < abilityResults.length; i++){ for (var i = 0; i < abilityResults.length; i++) {
multiclassSubclass.system[subclassFeaturesKey].abilities[i].uuid = abilityResults[i].uuid; multiclassSubclass.system[subclassFeaturesKey].abilities[i].uuid = abilityResults[i].uuid;
} }
} }
await this.actor.createEmbeddedDocuments('Item', [multiclassClass, ...multiclassFeatures, multiclassSubclass]); await this.actor.createEmbeddedDocuments('Item', [
multiclassClass,
...multiclassFeatures,
multiclassSubclass
]);
} }
this.close(); this.close();
} }
} }

View file

@ -1,51 +1,53 @@
const {HandlebarsApplicationMixin, ApplicationV2} = foundry.applications.api; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
export default class DhpMulticlassDialog extends HandlebarsApplicationMixin(ApplicationV2) { export default class DhpMulticlassDialog extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(actorName, actorClass, resolve){ constructor(actorName, actorClass, resolve) {
super({}); super({});
this.actorName = actorName; this.actorName = actorName;
this.actorClass = actorClass; this.actorClass = actorClass;
this.resolve = resolve; this.resolve = resolve;
this.classChoices = Array.from(game.items.reduce((acc, x) => { this.classChoices = Array.from(
if(x.type === 'class' && x.name !== actorClass.name){ game.items.reduce((acc, x) => {
if (x.type === 'class' && x.name !== actorClass.name) {
acc.add(x); acc.add(x);
} }
return acc; return acc;
}, new Set())); }, new Set())
);
this.subclassChoices = []; this.subclassChoices = [];
this.domainChoices = []; this.domainChoices = [];
this.data = { this.data = {
class: null, class: null,
subclass: null, subclass: null,
domain: null, domain: null
}; };
} }
get title(){ get title() {
return `${this.actorName} - Multiclass`; return `${this.actorName} - Multiclass`;
} }
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
classes: ["daggerheart", "views", "multiclass"], classes: ['daggerheart', 'views', 'multiclass'],
position: { width: 600, height: 'auto' }, position: { width: 600, height: 'auto' },
actions: { actions: {
selectClass: this.selectClass, selectClass: this.selectClass,
selectSubclass: this.selectSubclass, selectSubclass: this.selectSubclass,
selectDomain: this.selectDomain, selectDomain: this.selectDomain,
finish: this.finish, finish: this.finish
}, }
}; };
static PARTS = { static PARTS = {
form: { form: {
id: "levelup", id: 'levelup',
template: "systems/daggerheart/templates/views/multiclass.hbs" template: 'systems/daggerheart/templates/views/multiclass.hbs'
}
} }
};
async _prepareContext(_options) { async _prepareContext(_options) {
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
@ -61,37 +63,50 @@ export default class DhpMulticlassDialog extends HandlebarsApplicationMixin(Appl
static async selectClass(_, button) { static async selectClass(_, button) {
const oldClass = this.data.class; const oldClass = this.data.class;
this.data.class = this.data.class?.uuid === button.dataset.class ? null : await fromUuid(button.dataset.class); this.data.class = this.data.class?.uuid === button.dataset.class ? null : await fromUuid(button.dataset.class);
if(oldClass !== button.dataset.class){ if (oldClass !== button.dataset.class) {
this.data.subclass = null; this.data.subclass = null;
this.data.domain = null; this.data.domain = null;
this.subclassChoices = this.data.class ? this.data.class.system.subclasses : []; this.subclassChoices = this.data.class ? this.data.class.system.subclasses : [];
this.domainChoices = this.data.class ? this.data.class.system.domains.map(x => { this.domainChoices = this.data.class
? this.data.class.system.domains.map(x => {
const config = SYSTEM.DOMAIN.domains[x]; const config = SYSTEM.DOMAIN.domains[x];
return { name: game.i18n.localize(config.name), id: config.id, img: config.src, disabled: this.actorClass.system.domains.includes(config.id) }; return {
}) : []; name: game.i18n.localize(config.name),
id: config.id,
img: config.src,
disabled: this.actorClass.system.domains.includes(config.id)
};
})
: [];
} }
this.render(true); this.render(true);
} }
static async selectSubclass(_, button) { static async selectSubclass(_, button) {
this.data.subclass = this.data.subclass?.uuid === button.dataset.subclass ? null : this.subclassChoices.find(x => x.uuid === button.dataset.subclass); this.data.subclass =
this.data.subclass?.uuid === button.dataset.subclass
? null
: this.subclassChoices.find(x => x.uuid === button.dataset.subclass);
this.render(true); this.render(true);
} }
static async selectDomain(_, button) { static async selectDomain(_, button) {
const domain = this.data.domain?.id === button.dataset.domain ? null : this.domainChoices.find(x => x.id === button.dataset.domain);; const domain =
if(domain?.disabled) return; this.data.domain?.id === button.dataset.domain
? null
: this.domainChoices.find(x => x.id === button.dataset.domain);
if (domain?.disabled) return;
this.data.domain = domain; this.data.domain = domain;
this.render(true); this.render(true);
} }
static finish(){ static finish() {
this.close({}, this.data); this.close({}, this.data);
} }
async close(options={}, data=null) { async close(options = {}, data = null) {
this.resolve(data); this.resolve(data);
super.close(options); super.close(options);
} }

View file

@ -1,5 +1,5 @@
export default class NpcRollSelectionDialog extends FormApplication { export default class NpcRollSelectionDialog extends FormApplication {
constructor(experiences, resolve, isNpc){ constructor(experiences, resolve, isNpc) {
super({}, {}); super({}, {});
this.experiences = experiences; this.experiences = experiences;
@ -7,11 +7,11 @@ export default class NpcRollSelectionDialog extends FormApplication {
this.selectedExperiences = []; this.selectedExperiences = [];
this.data = { this.data = {
nrDice: 1, nrDice: 1,
advantage: null, advantage: null
}; };
} }
get title (){ get title() {
return 'Roll Options'; return 'Roll Options';
} }
@ -24,7 +24,7 @@ export default class NpcRollSelectionDialog extends FormApplication {
template: 'systems/daggerheart/templates/views/npcRollSelection.hbs', template: 'systems/daggerheart/templates/views/npcRollSelection.hbs',
closeOnSubmit: false, closeOnSubmit: false,
submitOnChange: true, submitOnChange: true,
classes: ["daggerheart", "views", "npc-roll-selection"], classes: ['daggerheart', 'views', 'npc-roll-selection']
}; };
const mergedOptions = foundry.utils.mergeObject(defaults, overrides); const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
@ -32,11 +32,14 @@ export default class NpcRollSelectionDialog extends FormApplication {
return mergedOptions; return mergedOptions;
} }
async getData(){ async getData() {
const context = super.getData(); const context = super.getData();
context.nrDice = this.data.nrDice; context.nrDice = this.data.nrDice;
context.advantage = this.data.advantage; context.advantage = this.data.advantage;
context.experiences = this.experiences.map(x => ({ ...x, selected: this.selectedExperiences.find(selected => selected.id === x.id) })); context.experiences = this.experiences.map(x => ({
...x,
selected: this.selectedExperiences.find(selected => selected.id === x.id)
}));
return context; return context;
} }
@ -52,7 +55,7 @@ export default class NpcRollSelectionDialog extends FormApplication {
html.find('.roll-dialog-chip').click(this.selectExperience.bind(this)); html.find('.roll-dialog-chip').click(this.selectExperience.bind(this));
} }
updateNrDice(value){ updateNrDice(value) {
this.data.nrDice += value; this.data.nrDice += value;
this.render(); this.render();
} }
@ -62,14 +65,16 @@ export default class NpcRollSelectionDialog extends FormApplication {
this.render(); this.render();
} }
selectExperience(event){ selectExperience(event) {
const experience = this.experiences[event.currentTarget.dataset.key]; const experience = this.experiences[event.currentTarget.dataset.key];
this.selectedExperiences = this.selectedExperiences.find(x => x.name === experience.name) ? this.selectedExperiences.filter(x => x.name !== experience.name) : [...this.selectedExperiences, experience]; this.selectedExperiences = this.selectedExperiences.find(x => x.name === experience.name)
? this.selectedExperiences.filter(x => x.name !== experience.name)
: [...this.selectedExperiences, experience];
this.render(); this.render();
} }
finish(){ finish() {
this.resolve({ ...this.data, experiences: this.selectedExperiences }); this.resolve({ ...this.data, experiences: this.selectedExperiences });
this.close(); this.close();
} }

View file

@ -1,7 +1,7 @@
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api; const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
export default class RollSelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) { export default class RollSelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(experiences, bonusDamage, hopeResource, resolve, isNpc){ constructor(experiences, bonusDamage, hopeResource, resolve, isNpc) {
super({}, {}); super({}, {});
this.experiences = experiences; this.experiences = experiences;
@ -9,31 +9,34 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
this.isNpc; this.isNpc;
this.selectedExperiences = []; this.selectedExperiences = [];
this.data = { this.data = {
diceOptions: [{ name: 'd12', value: 'd12' }, { name: 'd20', value: 'd20' }], diceOptions: [
{ name: 'd12', value: 'd12' },
{ name: 'd20', value: 'd20' }
],
hope: ['d12'], hope: ['d12'],
fear: ['d12'], fear: ['d12'],
advantage: null, advantage: null,
disadvantage: null, disadvantage: null,
bonusDamage: bonusDamage.reduce((acc, x) => { bonusDamage: bonusDamage.reduce((acc, x) => {
if(x.appliesOn === SYSTEM.EFFECTS.applyLocations.attackRoll.id){ if (x.appliesOn === SYSTEM.EFFECTS.applyLocations.attackRoll.id) {
acc.push(({ acc.push({
...x, ...x,
hopeUses: 0 hopeUses: 0
})); });
} }
return acc; return acc;
}, []), }, []),
hopeResource: hopeResource, hopeResource: hopeResource
}; };
} }
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
classes: ["daggerheart", "views", "roll-selection"], classes: ['daggerheart', 'views', 'roll-selection'],
position: { position: {
width: 400, width: 400,
height: "auto" height: 'auto'
}, },
actions: { actions: {
selectExperience: this.selectExperience, selectExperience: this.selectExperience,
@ -41,22 +44,22 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
increaseHopeUse: this.increaseHopeUse, increaseHopeUse: this.increaseHopeUse,
setAdvantage: this.setAdvantage, setAdvantage: this.setAdvantage,
setDisadvantage: this.setDisadvantage, setDisadvantage: this.setDisadvantage,
finish: this.finish, finish: this.finish
}, },
form: { form: {
handler: this.updateSelection, handler: this.updateSelection,
submitOnChange: true, submitOnChange: true,
submitOnClose: false, submitOnClose: false
} }
}; };
/** @override */ /** @override */
static PARTS = { static PARTS = {
damageSelection: { damageSelection: {
id: "damageSelection", id: 'damageSelection',
template: "systems/daggerheart/templates/views/rollSelection.hbs" template: 'systems/daggerheart/templates/views/rollSelection.hbs'
}
} }
};
get title() { get title() {
return `Roll Options`; return `Roll Options`;
@ -70,22 +73,25 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
context.fear = this.data.fear; context.fear = this.data.fear;
context.advantage = this.data.advantage; context.advantage = this.data.advantage;
context.disadvantage = this.data.disadvantage; context.disadvantage = this.data.disadvantage;
context.experiences = this.experiences.map(x => ({ ...x, selected: this.selectedExperiences.find(selected => selected.id === x.id) })); context.experiences = this.experiences.map(x => ({
...x,
selected: this.selectedExperiences.find(selected => selected.id === x.id)
}));
context.bonusDamage = this.data.bonusDamage; context.bonusDamage = this.data.bonusDamage;
context.hopeResource = this.data.hopeResource+1; context.hopeResource = this.data.hopeResource + 1;
context.hopeUsed = this.getHopeUsed(); context.hopeUsed = this.getHopeUsed();
return context; return context;
} }
static updateSelection(event, _, formData){ static updateSelection(event, _, formData) {
const { bonusDamage, ...rest } = foundry.utils.expandObject(formData.object); const { bonusDamage, ...rest } = foundry.utils.expandObject(formData.object);
for(var index in bonusDamage){ for (var index in bonusDamage) {
this.data.bonusDamage[index].initiallySelected = bonusDamage[index].initiallySelected; this.data.bonusDamage[index].initiallySelected = bonusDamage[index].initiallySelected;
if(bonusDamage[index].hopeUses){ if (bonusDamage[index].hopeUses) {
const value = Number.parseInt(bonusDamage[index].hopeUses); const value = Number.parseInt(bonusDamage[index].hopeUses);
if(!Number.isNaN(value)) this.data.bonusDamage[index].hopeUses = value; if (!Number.isNaN(value)) this.data.bonusDamage[index].hopeUses = value;
} }
} }
@ -93,53 +99,61 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
this.render(); this.render();
} }
static selectExperience(_, button){ static selectExperience(_, button) {
if(this.selectedExperiences.find(x => x.id === button.dataset.key)){ if (this.selectedExperiences.find(x => x.id === button.dataset.key)) {
this.selectedExperiences = this.selectedExperiences.filter(x => x.id !== button.dataset.key); this.selectedExperiences = this.selectedExperiences.filter(x => x.id !== button.dataset.key);
} else { } else {
this.selectedExperiences = [...this.selectedExperiences, this.experiences.find(x => x.id === button.dataset.key)]; this.selectedExperiences = [
...this.selectedExperiences,
this.experiences.find(x => x.id === button.dataset.key)
];
} }
this.render(); this.render();
} }
getHopeUsed(){ getHopeUsed() {
return this.data.bonusDamage.reduce((acc, x) => acc+x.hopeUses, 0); return this.data.bonusDamage.reduce((acc, x) => acc + x.hopeUses, 0);
} }
static decreaseHopeUse(_, button){ static decreaseHopeUse(_, button) {
const index = Number.parseInt(button.dataset.index); const index = Number.parseInt(button.dataset.index);
if(this.data.bonusDamage[index].hopeUses - 1 >= 0) { if (this.data.bonusDamage[index].hopeUses - 1 >= 0) {
this.data.bonusDamage[index].hopeUses -= 1; this.data.bonusDamage[index].hopeUses -= 1;
this.render(true); this.render(true);
} }
} }
static increaseHopeUse(_, button){ static increaseHopeUse(_, button) {
const index = Number.parseInt(button.dataset.index); const index = Number.parseInt(button.dataset.index);
if(this.data.bonusDamage[index].hopeUses <= this.data.hopeResource+1) { if (this.data.bonusDamage[index].hopeUses <= this.data.hopeResource + 1) {
this.data.bonusDamage[index].hopeUses += 1; this.data.bonusDamage[index].hopeUses += 1;
this.render(true); this.render(true);
} }
} }
static setAdvantage(){ static setAdvantage() {
this.data.advantage = this.data.advantage ? null : 'd6'; this.data.advantage = this.data.advantage ? null : 'd6';
this.data.disadvantage = null; this.data.disadvantage = null;
this.render(true); this.render(true);
} }
static setDisadvantage(){ static setDisadvantage() {
this.data.advantage = null; this.data.advantage = null;
this.data.disadvantage = this.data.disadvantage ? null : 'd6'; this.data.disadvantage = this.data.disadvantage ? null : 'd6';
this.render(true); this.render(true);
} }
static async finish(){ static async finish() {
const { diceOptions, ...rest } = this.data; const { diceOptions, ...rest } = this.data;
this.resolve({ ...rest, experiences: this.selectedExperiences, hopeUsed: this.getHopeUsed(), bonusDamage: this.data.bonusDamage.reduce((acc, x) => acc.concat(` + ${1+x.hopeUses}${x.value}`), "") }); this.resolve({
...rest,
experiences: this.selectedExperiences,
hopeUsed: this.getHopeUsed(),
bonusDamage: this.data.bonusDamage.reduce((acc, x) => acc.concat(` + ${1 + x.hopeUses}${x.value}`), '')
});
this.close(); this.close();
} }
} }

View file

@ -1,5 +1,5 @@
class DhpAutomationSettings extends FormApplication { class DhpAutomationSettings extends FormApplication {
constructor(object={}, options={}){ constructor(object = {}, options = {}) {
super(object, options); super(object, options);
} }
@ -12,7 +12,7 @@ class DhpAutomationSettings extends FormApplication {
template: 'systems/daggerheart/templates/views/automation-settings.hbs', template: 'systems/daggerheart/templates/views/automation-settings.hbs',
closeOnSubmit: true, closeOnSubmit: true,
submitOnChange: false, submitOnChange: false,
classes: ["daggerheart", "views", "settings"], classes: ['daggerheart', 'views', 'settings']
}; };
const mergedOptions = foundry.utils.mergeObject(defaults, overrides); const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
@ -20,7 +20,7 @@ class DhpAutomationSettings extends FormApplication {
return mergedOptions; return mergedOptions;
} }
async getData(){ async getData() {
const context = super.getData(); const context = super.getData();
context.settings = SYSTEM.SETTINGS.gameSettings.Automation; context.settings = SYSTEM.SETTINGS.gameSettings.Automation;
context.hope = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope); context.hope = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope);
@ -36,14 +36,14 @@ class DhpAutomationSettings extends FormApplication {
async _updateObject(_, formData) { async _updateObject(_, formData) {
const data = foundry.utils.expandObject(formData); const data = foundry.utils.expandObject(formData);
const updateSettingsKeys = Object.keys(data); const updateSettingsKeys = Object.keys(data);
for(var i = 0; i < updateSettingsKeys.length; i++){ for (var i = 0; i < updateSettingsKeys.length; i++) {
await game.settings.set(SYSTEM.id, updateSettingsKeys[i], data[updateSettingsKeys[i]]); await game.settings.set(SYSTEM.id, updateSettingsKeys[i], data[updateSettingsKeys[i]]);
} }
} }
} }
class DhpHomebrewSettings extends FormApplication { class DhpHomebrewSettings extends FormApplication {
constructor(object={}, options={}){ constructor(object = {}, options = {}) {
super(object, options); super(object, options);
} }
@ -56,7 +56,7 @@ class DhpHomebrewSettings extends FormApplication {
template: 'systems/daggerheart/templates/views/homebrew-settings.hbs', template: 'systems/daggerheart/templates/views/homebrew-settings.hbs',
closeOnSubmit: true, closeOnSubmit: true,
submitOnChange: false, submitOnChange: false,
classes: ["daggerheart", "views", "settings"], classes: ['daggerheart', 'views', 'settings']
}; };
const mergedOptions = foundry.utils.mergeObject(defaults, overrides); const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
@ -64,7 +64,7 @@ class DhpHomebrewSettings extends FormApplication {
return mergedOptions; return mergedOptions;
} }
async getData(){ async getData() {
const context = super.getData(); const context = super.getData();
context.settings = SYSTEM.SETTINGS.gameSettings.General; context.settings = SYSTEM.SETTINGS.gameSettings.General;
context.abilityArray = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.AbilityArray); context.abilityArray = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.AbilityArray);
@ -79,14 +79,14 @@ class DhpHomebrewSettings extends FormApplication {
async _updateObject(_, formData) { async _updateObject(_, formData) {
const data = foundry.utils.expandObject(formData); const data = foundry.utils.expandObject(formData);
const updateSettingsKeys = Object.keys(data); const updateSettingsKeys = Object.keys(data);
for(var i = 0; i < updateSettingsKeys.length; i++){ for (var i = 0; i < updateSettingsKeys.length; i++) {
await game.settings.set(SYSTEM.id, updateSettingsKeys[i], data[updateSettingsKeys[i]]); await game.settings.set(SYSTEM.id, updateSettingsKeys[i], data[updateSettingsKeys[i]]);
} }
} }
} }
class DhpRangeSettings extends FormApplication { class DhpRangeSettings extends FormApplication {
constructor(object={}, options={}){ constructor(object = {}, options = {}) {
super(object, options); super(object, options);
this.range = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.RangeMeasurement); this.range = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.RangeMeasurement);
@ -101,7 +101,7 @@ class DhpRangeSettings extends FormApplication {
template: 'systems/daggerheart/templates/views/range-settings.hbs', template: 'systems/daggerheart/templates/views/range-settings.hbs',
closeOnSubmit: false, closeOnSubmit: false,
submitOnChange: true, submitOnChange: true,
classes: ["daggerheart", "views", "settings"], classes: ['daggerheart', 'views', 'settings']
}; };
const mergedOptions = foundry.utils.mergeObject(defaults, overrides); const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
@ -109,11 +109,19 @@ class DhpRangeSettings extends FormApplication {
return mergedOptions; return mergedOptions;
} }
async getData(){ async getData() {
const context = super.getData(); const context = super.getData();
context.settings = SYSTEM.SETTINGS.gameSettings.General; context.settings = SYSTEM.SETTINGS.gameSettings.General;
context.range = this.range; context.range = this.range;
context.disabled = context.range.enabled && [context.range.melee, context.range.veryClose, context.range.close, context.range.far, context.range.veryFar].some(x => x === null || x === false); context.disabled =
context.range.enabled &&
[
context.range.melee,
context.range.veryClose,
context.range.close,
context.range.far,
context.range.veryFar
].some(x => x === null || x === false);
return context; return context;
} }
@ -121,9 +129,9 @@ class DhpRangeSettings extends FormApplication {
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
html.find(".range-reset").click(this.reset.bind(this)); html.find('.range-reset').click(this.reset.bind(this));
html.find(".save").click(this.save.bind(this)); html.find('.save').click(this.save.bind(this));
html.find(".close").click(this.close.bind(this)); html.find('.close').click(this.close.bind(this));
} }
async _updateObject(_, formData) { async _updateObject(_, formData) {
@ -132,7 +140,7 @@ class DhpRangeSettings extends FormApplication {
this.render(true); this.render(true);
} }
reset(){ reset() {
this.range = { this.range = {
enabled: false, enabled: false,
melee: 5, melee: 5,
@ -144,7 +152,7 @@ class DhpRangeSettings extends FormApplication {
this.render(true); this.render(true);
} }
async save(){ async save() {
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.RangeMeasurement, this.range); await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.RangeMeasurement, this.range);
this.close(); this.close();
} }
@ -154,44 +162,44 @@ export const registerDHPSettings = () => {
// const debouncedReload = foundry.utils.debounce(() => window.location.reload(), 100); // const debouncedReload = foundry.utils.debounce(() => window.location.reload(), 100);
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.AbilityArray, { game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.AbilityArray, {
name: game.i18n.localize("DAGGERHEART.Settings.General.AbilityArray.Name"), name: game.i18n.localize('DAGGERHEART.Settings.General.AbilityArray.Name'),
hint: game.i18n.localize("DAGGERHEART.Settings.General.AbilityArray.Hint"), hint: game.i18n.localize('DAGGERHEART.Settings.General.AbilityArray.Hint'),
scope: 'world', scope: 'world',
config: false, config: false,
type: String, type: String,
default: '[2,1,1,0,0,-1]', default: '[2,1,1,0,0,-1]'
}); });
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear, { game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear, {
name: game.i18n.localize("DAGGERHEART.Settings.Resources.Fear.Name"), name: game.i18n.localize('DAGGERHEART.Settings.Resources.Fear.Name'),
hint: game.i18n.localize("DAGGERHEART.Settings.Resources.Fear.Hint"), hint: game.i18n.localize('DAGGERHEART.Settings.Resources.Fear.Hint'),
scope: 'world', scope: 'world',
config: false, config: false,
type: Number, type: Number,
default: 0, default: 0
}); });
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope, { game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope, {
name: game.i18n.localize("DAGGERHEART.Settings.Automation.Hope.Name"), name: game.i18n.localize('DAGGERHEART.Settings.Automation.Hope.Name'),
hint: game.i18n.localize("DAGGERHEART.Settings.Automation.Hope.Hint"), hint: game.i18n.localize('DAGGERHEART.Settings.Automation.Hope.Hint'),
scope: 'world', scope: 'world',
config: false, config: false,
type: Boolean, type: Boolean,
default: false, default: false
}); });
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.ActionPoints, { game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.ActionPoints, {
name: game.i18n.localize("DAGGERHEART.Settings.Automation.ActionPoints.Name"), name: game.i18n.localize('DAGGERHEART.Settings.Automation.ActionPoints.Name'),
hint: game.i18n.localize("DAGGERHEART.Settings.Automation.ActionPoints.Hint"), hint: game.i18n.localize('DAGGERHEART.Settings.Automation.ActionPoints.Hint'),
scope: 'world', scope: 'world',
config: false, config: false,
type: Boolean, type: Boolean,
default: true, default: true
}); });
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.RangeMeasurement, { game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.RangeMeasurement, {
name: game.i18n.localize("DAGGERHEART.Settings.General.RangeMeasurement.Name"), name: game.i18n.localize('DAGGERHEART.Settings.General.RangeMeasurement.Name'),
hint: game.i18n.localize("DAGGERHEART.Settings.General.RangeMeasurement.Hint"), hint: game.i18n.localize('DAGGERHEART.Settings.General.RangeMeasurement.Hint'),
scope: 'world', scope: 'world',
config: false, config: false,
type: Object, type: Object,
@ -202,35 +210,34 @@ export const registerDHPSettings = () => {
close: 30, close: 30,
far: 60, far: 60,
veryFar: 120 veryFar: 120
}, }
}); });
game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.Automation.Name, { game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.Automation.Name, {
name: game.i18n.localize("DAGGERHEART.Settings.Menu.Automation.Name"), name: game.i18n.localize('DAGGERHEART.Settings.Menu.Automation.Name'),
label: game.i18n.localize("DAGGERHEART.Settings.Menu.Automation.Label"), label: game.i18n.localize('DAGGERHEART.Settings.Menu.Automation.Label'),
hint: game.i18n.localize("DAGGERHEART.Settings.Menu.Automation.Hint"), hint: game.i18n.localize('DAGGERHEART.Settings.Menu.Automation.Hint'),
icon: SYSTEM.SETTINGS.menu.Automation.Icon, icon: SYSTEM.SETTINGS.menu.Automation.Icon,
type: DhpAutomationSettings, type: DhpAutomationSettings,
restricted: true restricted: true
}); });
game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.Homebrew.Name, { game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.Homebrew.Name, {
name: game.i18n.localize("DAGGERHEART.Settings.Menu.Homebrew.Name"), name: game.i18n.localize('DAGGERHEART.Settings.Menu.Homebrew.Name'),
label: game.i18n.localize("DAGGERHEART.Settings.Menu.Homebrew.Label"), label: game.i18n.localize('DAGGERHEART.Settings.Menu.Homebrew.Label'),
hint: game.i18n.localize("DAGGERHEART.Settings.Menu.Homebrew.Hint"), hint: game.i18n.localize('DAGGERHEART.Settings.Menu.Homebrew.Hint'),
icon: SYSTEM.SETTINGS.menu.Homebrew.Icon, icon: SYSTEM.SETTINGS.menu.Homebrew.Icon,
type: DhpHomebrewSettings, type: DhpHomebrewSettings,
restricted: true restricted: true
}); });
game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.Range.Name, { game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.Range.Name, {
name: game.i18n.localize("DAGGERHEART.Settings.Menu.Range.Name"), name: game.i18n.localize('DAGGERHEART.Settings.Menu.Range.Name'),
label: game.i18n.localize("DAGGERHEART.Settings.Menu.Range.Label"), label: game.i18n.localize('DAGGERHEART.Settings.Menu.Range.Label'),
hint: game.i18n.localize("DAGGERHEART.Settings.Menu.Range.Hint"), hint: game.i18n.localize('DAGGERHEART.Settings.Menu.Range.Hint'),
icon: SYSTEM.SETTINGS.menu.Range.Icon, icon: SYSTEM.SETTINGS.menu.Range.Icon,
type: DhpRangeSettings, type: DhpRangeSettings,
restricted: true restricted: true
}); });
} };
// const {HandlebarsApplicationMixin, ApplicationV2} = foundry.applications.api; // const {HandlebarsApplicationMixin, ApplicationV2} = foundry.applications.api;

View file

@ -1,4 +1,3 @@
// import DhpApplicationMixin from '../daggerheart-sheet.mjs'; // import DhpApplicationMixin from '../daggerheart-sheet.mjs';
// export class Teest extends DhpApplicationMixin(ActorSheet) { // export class Teest extends DhpApplicationMixin(ActorSheet) {
@ -198,7 +197,7 @@ import DaggerheartSheet from './daggerheart-sheet.mjs';
const { ActorSheetV2 } = foundry.applications.sheets; const { ActorSheetV2 } = foundry.applications.sheets;
export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) { export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
constructor(options={}){ constructor(options = {}) {
super(options); super(options);
this.editMode = false; this.editMode = false;
@ -206,8 +205,8 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: "daggerheart-adversary", id: 'daggerheart-adversary',
classes: ["daggerheart", "sheet", "adversary"], classes: ['daggerheart', 'sheet', 'adversary'],
position: { width: 600 }, position: { width: 600 },
actions: { actions: {
viewMove: this.viewMove, viewMove: this.viewMove,
@ -221,21 +220,21 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
addExperience: this.addExperience, addExperience: this.addExperience,
removeExperience: this.removeExperience, removeExperience: this.removeExperience,
toggleHP: this.toggleHP, toggleHP: this.toggleHP,
toggleStress: this.toggleStress, toggleStress: this.toggleStress
}, },
form: { form: {
handler: this.updateForm, handler: this.updateForm,
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false
}, }
}; };
static PARTS = { static PARTS = {
form: { form: {
id: "feature", id: 'feature',
template: "systems/daggerheart/templates/sheets/adversary.hbs" template: 'systems/daggerheart/templates/sheets/adversary.hbs'
}
} }
};
async _prepareContext(_options) { async _prepareContext(_options) {
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
@ -252,92 +251,118 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
attack: { attack: {
name: this.document.system.attack.name, name: this.document.system.attack.name,
attackModifier: this.document.system.attackModifier, attackModifier: this.document.system.attackModifier,
range: this.document.system.attack.range ? game.i18n.localize(SYSTEM.GENERAL.range[this.document.system.attack.range].name) : null, range: this.document.system.attack.range
? game.i18n.localize(SYSTEM.GENERAL.range[this.document.system.attack.range].name)
: null,
damage: { damage: {
value: this.document.system.attack.damage.value, value: this.document.system.attack.damage.value,
type: this.document.system.attack.damage.type, type: this.document.system.attack.damage.type,
typeName: this.document.system.attack.damage.type ? game.i18n.localize(SYSTEM.GENERAL.damageTypes[this.document.system.attack.damage.type].abbreviation).toLowerCase() : null, typeName: this.document.system.attack.damage.type
}, ? game.i18n
.localize(
SYSTEM.GENERAL.damageTypes[this.document.system.attack.damage.type].abbreviation
)
.toLowerCase()
: null
}
}, },
damageThresholds: this.document.system.damageThresholds, damageThresholds: this.document.system.damageThresholds,
difficulty: this.document.system.difficulty, difficulty: this.document.system.difficulty,
hp: { ...this.document.system.resources.health, lastRowIndex: Math.floor(this.document.system.resources.health.max/5)*5 }, hp: {
stress: { ...this.document.system.resources.stress, lastRowIndex: Math.floor(this.document.system.resources.stress.max/5)*5 }, ...this.document.system.resources.health,
moves: this.document.system.moves, lastRowIndex: Math.floor(this.document.system.resources.health.max / 5) * 5
},
stress: {
...this.document.system.resources.stress,
lastRowIndex: Math.floor(this.document.system.resources.stress.max / 5) * 5
},
moves: this.document.system.moves
}; };
return context; return context;
} }
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
await this.document.update(formData.object) await this.document.update(formData.object);
this.render(); this.render();
} }
static async viewMove(_, button){ static async viewMove(_, button) {
const move = await fromUuid(button.dataset.move); const move = await fromUuid(button.dataset.move);
move.sheet.render(true); move.sheet.render(true);
} }
static async addMove(){ static async addMove() {
const result = await this.document.createEmbeddedDocuments("Item", [{ const result = await this.document.createEmbeddedDocuments('Item', [
{
name: game.i18n.localize('DAGGERHEART.Sheets.Adversary.NewMove'), name: game.i18n.localize('DAGGERHEART.Sheets.Adversary.NewMove'),
type: 'feature', type: 'feature'
}]); }
]);
await result[0].sheet.render(true); await result[0].sheet.render(true);
} }
static async removeMove(_, button){ static async removeMove(_, button) {
await this.document.items.find(x => x.uuid === button.dataset.move).delete(); await this.document.items.find(x => x.uuid === button.dataset.move).delete();
} }
static toggleEditMode(){ static toggleEditMode() {
this.editMode = !this.editMode; this.editMode = !this.editMode;
this.render(); this.render();
} }
static async addMotive(){ static async addMotive() {
await this.document.update({ "system.motivesAndTactics": [...this.document.system.motivesAndTactics, ''] }); await this.document.update({ 'system.motivesAndTactics': [...this.document.system.motivesAndTactics, ''] });
} }
static async removeMotive(button){ static async removeMotive(button) {
await this.document.update({ "system.motivesAndTactics": this.document.system.motivesAndTactics.filter((_, index) => index !== Number.parseInt(button.dataset.motive) )}); await this.document.update({
'system.motivesAndTactics': this.document.system.motivesAndTactics.filter(
(_, index) => index !== Number.parseInt(button.dataset.motive)
)
});
} }
static async reactionRoll(event){ static async reactionRoll(event) {
const { roll, diceResults, modifiers } = await this.actor.diceRoll({ title: `${this.actor.name} - Reaction Roll`, value: 0 }, event.shiftKey); const { roll, diceResults, modifiers } = await this.actor.diceRoll(
{ title: `${this.actor.name} - Reaction Roll`, value: 0 },
event.shiftKey
);
const cls = getDocumentClass("ChatMessage"); const cls = getDocumentClass('ChatMessage');
const msg = new cls({ const msg = new cls({
type: 'adversaryRoll', type: 'adversaryRoll',
system: { system: {
roll: roll._formula, roll: roll._formula,
total: roll._total, total: roll._total,
modifiers: modifiers, modifiers: modifiers,
diceResults: diceResults, diceResults: diceResults
}, },
content: "systems/daggerheart/templates/chat/adversary-roll.hbs", content: 'systems/daggerheart/templates/chat/adversary-roll.hbs',
rolls: [roll] rolls: [roll]
}); });
cls.create(msg.toObject()); cls.create(msg.toObject());
} }
static async attackRoll(event, button){ static async attackRoll(event, button) {
const modifier = Number.parseInt(button.dataset.value); const modifier = Number.parseInt(button.dataset.value);
const { roll, diceResults, modifiers } = await this.actor.diceRoll({ title: `${this.actor.name} - Attack Roll`, value: modifier }, event.shiftKey); const { roll, diceResults, modifiers } = await this.actor.diceRoll(
{ title: `${this.actor.name} - Attack Roll`, value: modifier },
event.shiftKey
);
const targets = Array.from(game.user.targets).map(x => ({ const targets = Array.from(game.user.targets).map(x => ({
id: x.id, id: x.id,
name: x.actor.name, name: x.actor.name,
img: x.actor.img, img: x.actor.img,
difficulty: x.actor.system.difficulty, difficulty: x.actor.system.difficulty,
evasion: x.actor.system.evasion, evasion: x.actor.system.evasion
})); }));
const cls = getDocumentClass("ChatMessage"); const cls = getDocumentClass('ChatMessage');
const msg = new cls({ const msg = new cls({
type: 'adversaryRoll', type: 'adversaryRoll',
system: { system: {
@ -346,32 +371,38 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
modifiers: modifiers, modifiers: modifiers,
diceResults: diceResults, diceResults: diceResults,
targets: targets, targets: targets,
damage: { value: button.dataset.damage, type: button.dataset.damageType }, damage: { value: button.dataset.damage, type: button.dataset.damageType }
}, },
content: "systems/daggerheart/templates/chat/adversary-attack-roll.hbs", content: 'systems/daggerheart/templates/chat/adversary-attack-roll.hbs',
rolls: [roll] rolls: [roll]
}); });
cls.create(msg.toObject()); cls.create(msg.toObject());
} }
static async addExperience(){ static async addExperience() {
await this.document.update({ "system.experiences": [...this.document.system.experiences, { name: 'Experience', value: 1 }] }); await this.document.update({
'system.experiences': [...this.document.system.experiences, { name: 'Experience', value: 1 }]
});
} }
static async removeExperience(_, button){ static async removeExperience(_, button) {
await this.document.update({ "system.experiences": this.document.system.experiences.filter((_, index) => index !== Number.parseInt(button.dataset.experience) )}); await this.document.update({
'system.experiences': this.document.system.experiences.filter(
(_, index) => index !== Number.parseInt(button.dataset.experience)
)
});
} }
static async toggleHP(_, button){ static async toggleHP(_, button) {
const index = Number.parseInt(button.dataset.index); const index = Number.parseInt(button.dataset.index);
const newHP = index < this.document.system.resources.health.value ? index : index+1; const newHP = index < this.document.system.resources.health.value ? index : index + 1;
await this.document.update({ "system.resources.health.value": newHP }); await this.document.update({ 'system.resources.health.value': newHP });
} }
static async toggleStress(_, button){ static async toggleStress(_, button) {
const index = Number.parseInt(button.dataset.index); const index = Number.parseInt(button.dataset.index);
const newStress = index < this.document.system.resources.stress.value ? index : index+1; const newStress = index < this.document.system.resources.stress.value ? index : index + 1;
await this.document.update({ "system.resources.stress.value": newStress }); await this.document.update({ 'system.resources.stress.value': newStress });
} }
} }

View file

@ -24,7 +24,6 @@
// return context; // return context;
// } // }
// async _handleAction(action, event, button) { // async _handleAction(action, event, button) {
// switch(action){ // switch(action){
// case 'editAbility': // case 'editAbility':
@ -62,27 +61,27 @@ const { ItemSheetV2 } = foundry.applications.sheets;
export default class AncestrySheet extends DaggerheartSheet(ItemSheetV2) { export default class AncestrySheet extends DaggerheartSheet(ItemSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: "daggerheart-ancestry", id: 'daggerheart-ancestry',
classes: ["daggerheart", "sheet", "heritage"], classes: ['daggerheart', 'sheet', 'heritage'],
position: { width: 600 }, position: { width: 600 },
actions: { actions: {
editAbility: this.editAbility, editAbility: this.editAbility,
deleteAbility: this.deleteAbility, deleteAbility: this.deleteAbility
}, },
form: { form: {
handler: this.updateForm, handler: this.updateForm,
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false
}, },
dragDrop: [{ dragSelector: null, dropSelector: null }], dragDrop: [{ dragSelector: null, dropSelector: null }]
}; };
static PARTS = { static PARTS = {
form: { form: {
id: "feature", id: 'feature',
template: "systems/daggerheart/templates/sheets/ancestry.hbs" template: 'systems/daggerheart/templates/sheets/ancestry.hbs'
}
} }
};
async _prepareContext(_options) { async _prepareContext(_options) {
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
@ -92,26 +91,33 @@ export default class AncestrySheet extends DaggerheartSheet(ItemSheetV2) {
} }
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
await this.document.update(formData.object) await this.document.update(formData.object);
this.render(); this.render();
} }
static async editAbility(_, button){ static async editAbility(_, button) {
const feature = await fromUuid(button.dataset.ability); const feature = await fromUuid(button.dataset.ability);
feature.sheet.render(true); feature.sheet.render(true);
} }
static async deleteAbility(event, button){ static async deleteAbility(event, button) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
await this.item.update({ "system.abilities": this.item.system.abilities.filter(x => x.uuid !== button.dataset.ability) }) await this.item.update({
'system.abilities': this.item.system.abilities.filter(x => x.uuid !== button.dataset.ability)
});
} }
async _onDrop(event) { async _onDrop(event) {
const data = TextEditor.getDragEventData(event); const data = TextEditor.getDragEventData(event);
const item = await fromUuid(data.uuid); const item = await fromUuid(data.uuid);
if(item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.ancestry.id) { if (item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.ancestry.id) {
await this.document.update({ "system.abilities": [...this.document.system.abilities, { img: item.img, name: item.name, uuid: item.uuid }] }); await this.document.update({
'system.abilities': [
...this.document.system.abilities,
{ img: item.img, name: item.name, uuid: item.uuid }
]
});
} }
} }
} }

View file

@ -20,7 +20,6 @@
// return context; // return context;
// } // }
// async _handleAction(action, event, button) { // async _handleAction(action, event, button) {
// switch(action){ // switch(action){
// } // }
@ -32,23 +31,23 @@ const { ItemSheetV2 } = foundry.applications.sheets;
export default class ArmorSheet extends DaggerheartSheet(ItemSheetV2) { export default class ArmorSheet extends DaggerheartSheet(ItemSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: "daggerheart-armor", id: 'daggerheart-armor',
classes: ["daggerheart", "sheet", "armor"], classes: ['daggerheart', 'sheet', 'armor'],
position: { width: 400 }, position: { width: 400 },
form: { form: {
handler: this.updateForm, handler: this.updateForm,
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false
}, },
dragDrop: [{ dragSelector: null, dropSelector: null }], dragDrop: [{ dragSelector: null, dropSelector: null }]
}; };
static PARTS = { static PARTS = {
form: { form: {
id: "feature", id: 'feature',
template: "systems/daggerheart/templates/sheets/armor.hbs" template: 'systems/daggerheart/templates/sheets/armor.hbs'
}
} }
};
async _prepareContext(_options) { async _prepareContext(_options) {
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
@ -59,7 +58,7 @@ export default class ArmorSheet extends DaggerheartSheet(ItemSheetV2) {
} }
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
await this.document.update(formData.object) await this.document.update(formData.object);
this.render(); this.render();
} }
} }

View file

@ -210,14 +210,14 @@
// } // }
import DaggerheartSheet from './daggerheart-sheet.mjs'; import DaggerheartSheet from './daggerheart-sheet.mjs';
import Tagify from "@yaireo/tagify"; import Tagify from '@yaireo/tagify';
const { ItemSheetV2 } = foundry.applications.sheets; const { ItemSheetV2 } = foundry.applications.sheets;
export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) { export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: "daggerheart-class", id: 'daggerheart-class',
classes: ["daggerheart", "sheet", "class"], classes: ['daggerheart', 'sheet', 'class'],
position: { width: 600 }, position: { width: 600 },
actions: { actions: {
removeSubclass: this.removeSubclass, removeSubclass: this.removeSubclass,
@ -228,13 +228,12 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
viewItem: this.viewItem, viewItem: this.viewItem,
removePrimaryWeapon: this.removePrimaryWeapon, removePrimaryWeapon: this.removePrimaryWeapon,
removeSecondaryWeapon: this.removeSecondaryWeapon, removeSecondaryWeapon: this.removeSecondaryWeapon,
removeArmor: this.removeArmor, removeArmor: this.removeArmor
}, },
form: { form: {
handler: this.updateForm, handler: this.updateForm,
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false
}, },
dragDrop: [ dragDrop: [
{ dragSelector: '.suggested-item', dropSelector: null }, { dragSelector: '.suggested-item', dropSelector: null },
@ -244,25 +243,39 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
{ dragSelector: null, dropSelector: '.primary-weapon-section' }, { dragSelector: null, dropSelector: '.primary-weapon-section' },
{ dragSelector: null, dropSelector: '.secondary-weapon-section' }, { dragSelector: null, dropSelector: '.secondary-weapon-section' },
{ dragSelector: null, dropSelector: '.armor-section' }, { dragSelector: null, dropSelector: '.armor-section' },
{ dragSelector: null, dropSelector: null }, { dragSelector: null, dropSelector: null }
] ]
}; };
static PARTS = { static PARTS = {
form: { form: {
id: "feature", id: 'feature',
template: "systems/daggerheart/templates/sheets/class.hbs" template: 'systems/daggerheart/templates/sheets/class.hbs'
}
} }
};
_getTabs() { _getTabs() {
const tabs = { const tabs = {
features: { active: true, cssClass: '', group: 'primary', id: 'features', icon: null, label: game.i18n.localize('DAGGERHEART.Sheets.Class.Tabs.Features') }, features: {
guide: { active: false, cssClass: '', group: 'primary', id: 'guide', icon: null, label: game.i18n.localize('DAGGERHEART.Sheets.Class.Tabs.Guide') }, active: true,
cssClass: '',
group: 'primary',
id: 'features',
icon: null,
label: game.i18n.localize('DAGGERHEART.Sheets.Class.Tabs.Features')
},
guide: {
active: false,
cssClass: '',
group: 'primary',
id: 'guide',
icon: null,
label: game.i18n.localize('DAGGERHEART.Sheets.Class.Tabs.Guide')
} }
for ( const v of Object.values(tabs) ) { };
for (const v of Object.values(tabs)) {
v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active; v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active;
v.cssClass = v.active ? "active" : ""; v.cssClass = v.active ? 'active' : '';
} }
return tabs; return tabs;
@ -273,29 +286,35 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
const domainInput = htmlElement.querySelector('.domain-input'); const domainInput = htmlElement.querySelector('.domain-input');
const domainTagify = new Tagify(domainInput, { const domainTagify = new Tagify(domainInput, {
tagTextProp: "name", tagTextProp: 'name',
enforceWhitelist: true, enforceWhitelist: true,
whitelist : Object.keys(SYSTEM.DOMAIN.domains).map(key => { whitelist: Object.keys(SYSTEM.DOMAIN.domains).map(key => {
const domain = SYSTEM.DOMAIN.domains[key]; const domain = SYSTEM.DOMAIN.domains[key];
return { value: key, name: game.i18n.localize(domain.label), src: domain.src, background: domain.background }; return {
value: key,
name: game.i18n.localize(domain.label),
src: domain.src,
background: domain.background
};
}), }),
maxTags: 2, maxTags: 2,
callbacks : { invalid: this.onAddTag }, callbacks: { invalid: this.onAddTag },
dropdown : { dropdown: {
mapValueTo: 'name', mapValueTo: 'name',
searchKeys: ['name'], searchKeys: ['name'],
enabled: 0, enabled: 0,
maxItems: 20, maxItems: 20,
closeOnSelect : true, closeOnSelect: true,
highlightFirst: false, highlightFirst: false
}, },
templates: { templates: {
tag(tagData){ //z-index: unset; background-image: ${tagData.background}; Maybe a domain specific background for the chips? tag(tagData) {
return `<tag title="${(tagData.title || tagData.value)}" //z-index: unset; background-image: ${tagData.background}; Maybe a domain specific background for the chips?
return `<tag title="${tagData.title || tagData.value}"
contenteditable='false' contenteditable='false'
spellcheck='false' spellcheck='false'
tabIndex="${this.settings.a11y.focusableTags ? 0 : -1}" tabIndex="${this.settings.a11y.focusableTags ? 0 : -1}"
class="${this.settings.classNames.tag} ${tagData.class ? tagData.class : ""}" class="${this.settings.classNames.tag} ${tagData.class ? tagData.class : ''}"
${this.getAttributes(tagData)}> ${this.getAttributes(tagData)}>
<x class="${this.settings.classNames.tagX}" role='button' aria-label='remove tag'></x> <x class="${this.settings.classNames.tagX}" role='button' aria-label='remove tag'></x>
<div> <div>
@ -303,7 +322,8 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
<img src="${tagData.src}"></i> <img src="${tagData.src}"></i>
</div> </div>
</tag>`; </tag>`;
}} }
}
}); });
domainTagify.on('change', this.onDomainSelect.bind(this)); domainTagify.on('change', this.onDomainSelect.bind(this));
@ -319,100 +339,144 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
} }
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
await this.document.update(formData.object) await this.document.update(formData.object);
this.render(); this.render();
} }
onAddTag(e){ onAddTag(e) {
if( e.detail.index ===2 ){ if (e.detail.index === 2) {
ui.notifications.info(game.i18n.localize("DAGGERHEART.Notification.Info.ClassCanOnlyHaveTwoDomains")); ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.ClassCanOnlyHaveTwoDomains'));
} }
} }
async onDomainSelect(event) { async onDomainSelect(event) {
const domains = event.detail?.value ? JSON.parse(event.detail.value) : []; const domains = event.detail?.value ? JSON.parse(event.detail.value) : [];
await this.document.update({ "system.domains": domains.map(x => x.value) }); await this.document.update({ 'system.domains': domains.map(x => x.value) });
this.render(true); this.render(true);
} }
static async removeSubclass(_, button){ static async removeSubclass(_, button) {
await this.document.update({ "system.subclasses": this.document.system.subclasses.filter(x => x.uuid !== button.dataset.subclass)}); await this.document.update({
'system.subclasses': this.document.system.subclasses.filter(x => x.uuid !== button.dataset.subclass)
});
} }
static async viewSubclass(_, button){ static async viewSubclass(_, button) {
const subclass = await fromUuid(button.dataset.subclass); const subclass = await fromUuid(button.dataset.subclass);
subclass.sheet.render(true); subclass.sheet.render(true);
} }
static async removeFeature(_, button){ static async removeFeature(_, button) {
await this.document.update({ "system.features": this.document.system.features.filter(x => x.uuid !== button.dataset.feature)}); await this.document.update({
'system.features': this.document.system.features.filter(x => x.uuid !== button.dataset.feature)
});
} }
static async viewFeature(_, button){ static async viewFeature(_, button) {
const feature = await fromUuid(button.dataset.feature); const feature = await fromUuid(button.dataset.feature);
feature.sheet.render(true); feature.sheet.render(true);
} }
static async removeItem(event, button){ static async removeItem(event, button) {
event.stopPropagation(); event.stopPropagation();
const type = button.dataset.type; const type = button.dataset.type;
const path = `system.inventory.${type}`; const path = `system.inventory.${type}`;
await this.document.update({ [path]: this.document.system.inventory[type].filter(x => x.uuid !== button.dataset.item)}); await this.document.update({
[path]: this.document.system.inventory[type].filter(x => x.uuid !== button.dataset.item)
});
} }
static async viewItem(_, button){ static async viewItem(_, button) {
const item = await fromUuid(button.dataset.item); const item = await fromUuid(button.dataset.item);
item.sheet.render(true); item.sheet.render(true);
} }
static async removePrimaryWeapon(event){ static async removePrimaryWeapon(event) {
event.stopPropagation(); event.stopPropagation();
await this.document.update({ "system.characterGuide.suggestedPrimaryWeapon": null }, { diff: false }); await this.document.update({ 'system.characterGuide.suggestedPrimaryWeapon': null }, { diff: false });
} }
static async removeSecondaryWeapon(event){ static async removeSecondaryWeapon(event) {
event.stopPropagation(); event.stopPropagation();
await this.document.update({ "system.characterGuide.suggestedSecondaryWeapon": null }, { diff: false }); await this.document.update({ 'system.characterGuide.suggestedSecondaryWeapon': null }, { diff: false });
} }
static async removeArmor(event){ static async removeArmor(event) {
event.stopPropagation(); event.stopPropagation();
await this.document.update({ "system.characterGuide.suggestedArmor": null }, { diff: false }); await this.document.update({ 'system.characterGuide.suggestedArmor': null }, { diff: false });
} }
async _onDrop(event) { async _onDrop(event) {
const data = TextEditor.getDragEventData(event); const data = TextEditor.getDragEventData(event);
const item = await fromUuid(data.uuid); const item = await fromUuid(data.uuid);
if(item.type === 'subclass') { if (item.type === 'subclass') {
await this.document.update({ "system.subclasses": [...this.document.system.subclasses, { img: item.img, name: item.name, uuid: item.uuid }] }); await this.document.update({
'system.subclasses': [
...this.document.system.subclasses,
{ img: item.img, name: item.name, uuid: item.uuid }
]
});
} else if (item.type === 'feature') {
await this.document.update({
'system.features': [
...this.document.system.features,
{ img: item.img, name: item.name, uuid: item.uuid }
]
});
} else if (item.type === 'weapon') {
if (event.currentTarget.classList.contains('primary-weapon-section')) {
if (!this.document.system.characterGuide.suggestedPrimaryWeapon && !item.system.secondary)
await this.document.update({
'system.characterGuide.suggestedPrimaryWeapon': {
img: item.img,
name: item.name,
uuid: item.uuid
} }
else if(item.type === 'feature') { });
} else if (event.currentTarget.classList.contains('secondary-weapon-section')) {
await this.document.update({ "system.features": [...this.document.system.features, { img: item.img, name: item.name, uuid: item.uuid }] }); if (!this.document.system.characterGuide.suggestedSecondaryWeapon && item.system.secondary)
await this.document.update({
'system.characterGuide.suggestedSecondaryWeapon': {
img: item.img,
name: item.name,
uuid: item.uuid
} }
else if(item.type === 'weapon'){ });
if(event.currentTarget.classList.contains('primary-weapon-section')){
if(!this.document.system.characterGuide.suggestedPrimaryWeapon && !item.system.secondary) await this.document.update({ "system.characterGuide.suggestedPrimaryWeapon": { img: item.img, name: item.name, uuid: item.uuid } });
} else if(event.currentTarget.classList.contains('secondary-weapon-section')){
if(!this.document.system.characterGuide.suggestedSecondaryWeapon && item.system.secondary) await this.document.update({ "system.characterGuide.suggestedSecondaryWeapon": { img: item.img, name: item.name, uuid: item.uuid } });
} }
} else if (item.type === 'armor') {
if (event.currentTarget.classList.contains('armor-section')) {
if (!this.document.system.characterGuide.suggestedArmor)
await this.document.update({
'system.characterGuide.suggestedArmor': { img: item.img, name: item.name, uuid: item.uuid }
});
} }
else if(item.type === 'armor'){ } else if (event.currentTarget.classList.contains('choice-a-section')) {
if(event.currentTarget.classList.contains('armor-section')){ if (item.type === 'miscellaneous' || item.type === 'consumable') {
if(!this.document.system.characterGuide.suggestedArmor) await this.document.update({ "system.characterGuide.suggestedArmor": { img: item.img, name: item.name, uuid: item.uuid } }); if (this.document.system.inventory.choiceA.length < 2)
await this.document.update({
'system.inventory.choiceA': [
...this.document.system.inventory.choiceA,
{ img: item.img, name: item.name, uuid: item.uuid }
]
});
} }
} } else if (item.type === 'miscellaneous') {
else if(event.currentTarget.classList.contains('choice-a-section')){ if (event.currentTarget.classList.contains('take-section')) {
if(item.type === 'miscellaneous' || item.type === 'consumable'){ if (this.document.system.inventory.take.length < 3)
if(this.document.system.inventory.choiceA.length < 2) await this.document.update({ "system.inventory.choiceA": [...this.document.system.inventory.choiceA, { img: item.img, name: item.name, uuid: item.uuid }] }); await this.document.update({
} 'system.inventory.take': [
} ...this.document.system.inventory.take,
else if(item.type === 'miscellaneous'){ { img: item.img, name: item.name, uuid: item.uuid }
if(event.currentTarget.classList.contains('take-section')){ ]
if(this.document.system.inventory.take.length < 3) await this.document.update({ "system.inventory.take": [...this.document.system.inventory.take, { img: item.img, name: item.name, uuid: item.uuid }] }); });
} } else if (event.currentTarget.classList.contains('choice-b-section')) {
else if(event.currentTarget.classList.contains('choice-b-section')){ if (this.document.system.inventory.choiceB.length < 2)
if(this.document.system.inventory.choiceB.length < 2) await this.document.update({ "system.inventory.choiceB": [...this.document.system.inventory.choiceB, { img: item.img, name: item.name, uuid: item.uuid }] }); await this.document.update({
'system.inventory.choiceB': [
...this.document.system.inventory.choiceB,
{ img: item.img, name: item.name, uuid: item.uuid }
]
});
} }
} }
} }

View file

@ -24,7 +24,6 @@
// return context; // return context;
// } // }
// async _handleAction(action, event, button) { // async _handleAction(action, event, button) {
// switch(action){ // switch(action){
// case 'editAbility': // case 'editAbility':
@ -62,27 +61,27 @@ const { ItemSheetV2 } = foundry.applications.sheets;
export default class CommunitySheet extends DaggerheartSheet(ItemSheetV2) { export default class CommunitySheet extends DaggerheartSheet(ItemSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: "daggerheart-community", id: 'daggerheart-community',
classes: ["daggerheart", "sheet", "heritage"], classes: ['daggerheart', 'sheet', 'heritage'],
position: { width: 600 }, position: { width: 600 },
actions: { actions: {
editAbility: this.editAbility, editAbility: this.editAbility,
deleteAbility: this.deleteAbility, deleteAbility: this.deleteAbility
}, },
form: { form: {
handler: this.updateForm, handler: this.updateForm,
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false
}, },
dragDrop: [{ dragSelector: null, dropSelector: null }], dragDrop: [{ dragSelector: null, dropSelector: null }]
}; };
static PARTS = { static PARTS = {
form: { form: {
id: "feature", id: 'feature',
template: "systems/daggerheart/templates/sheets/community.hbs" template: 'systems/daggerheart/templates/sheets/community.hbs'
}
} }
};
async _prepareContext(_options) { async _prepareContext(_options) {
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
@ -92,26 +91,33 @@ export default class CommunitySheet extends DaggerheartSheet(ItemSheetV2) {
} }
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
await this.document.update(formData.object) await this.document.update(formData.object);
this.render(); this.render();
} }
static async editAbility(_, button){ static async editAbility(_, button) {
const feature = await fromUuid(button.dataset.ability); const feature = await fromUuid(button.dataset.ability);
feature.sheet.render(true); feature.sheet.render(true);
} }
static async deleteAbility(event, button){ static async deleteAbility(event, button) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
await this.item.update({ "system.abilities": this.item.system.abilities.filter(x => x.uuid !== button.dataset.ability) }) await this.item.update({
'system.abilities': this.item.system.abilities.filter(x => x.uuid !== button.dataset.ability)
});
} }
async _onDrop(event) { async _onDrop(event) {
const data = TextEditor.getDragEventData(event); const data = TextEditor.getDragEventData(event);
const item = await fromUuid(data.uuid); const item = await fromUuid(data.uuid);
if(item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.community.id) { if (item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.community.id) {
await this.document.update({ "system.abilities": [...this.document.system.abilities, { img: item.img, name: item.name, uuid: item.uuid }] }); await this.document.update({
'system.abilities': [
...this.document.system.abilities,
{ img: item.img, name: item.name, uuid: item.uuid }
]
});
} }
} }
} }

View file

@ -26,22 +26,22 @@ const { ItemSheetV2 } = foundry.applications.sheets;
export default class ConsumableSheet extends DaggerheartSheet(ItemSheetV2) { export default class ConsumableSheet extends DaggerheartSheet(ItemSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: "daggerheart-consumable", id: 'daggerheart-consumable',
classes: ["daggerheart", "sheet", "consumable"], classes: ['daggerheart', 'sheet', 'consumable'],
position: { width: 480 }, position: { width: 480 },
form: { form: {
handler: this.updateForm, handler: this.updateForm,
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false
}, }
}; };
static PARTS = { static PARTS = {
form: { form: {
id: "feature", id: 'feature',
template: "systems/daggerheart/templates/sheets/consumable.hbs" template: 'systems/daggerheart/templates/sheets/consumable.hbs'
}
} }
};
async _prepareContext(_options) { async _prepareContext(_options) {
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
@ -51,7 +51,7 @@ export default class ConsumableSheet extends DaggerheartSheet(ItemSheetV2) {
} }
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
await this.document.update(formData.object) await this.document.update(formData.object);
this.render(); this.render();
} }
} }

View file

@ -2,7 +2,7 @@ const { HandlebarsApplicationMixin } = foundry.applications.api;
export default function DhpApplicationMixin(Base) { export default function DhpApplicationMixin(Base) {
return class DhpSheetV2 extends HandlebarsApplicationMixin(Base) { return class DhpSheetV2 extends HandlebarsApplicationMixin(Base) {
constructor(options={}){ constructor(options = {}) {
super(options); super(options);
this._dragDrop = this._createDragDropHandlers(); this._dragDrop = this._createDragDropHandlers();
@ -17,15 +17,15 @@ export default function DhpApplicationMixin(Base) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
position: { position: {
width: 480, width: 480,
height: "auto" height: 'auto'
}, },
actions: { actions: {
onEditImage: this._onEditImage onEditImage: this._onEditImage
}, },
dragDrop: [], dragDrop: []
}; };
async _prepareContext(_options, objectPath='document') { async _prepareContext(_options, objectPath = 'document') {
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
context.source = this[objectPath].toObject(); context.source = this[objectPath].toObject();
context.fields = this[objectPath].schema.fields; context.fields = this[objectPath].schema.fields;
@ -40,7 +40,7 @@ export default function DhpApplicationMixin(Base) {
const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {}; const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {};
const fp = new FilePicker({ const fp = new FilePicker({
current, current,
type: "image", type: 'image',
redirectToRoot: img ? [img] : [], redirectToRoot: img ? [img] : [],
callback: async path => this._updateImage.bind(this)(path), callback: async path => this._updateImage.bind(this)(path),
top: this.position.top + 40, top: this.position.top + 40,
@ -49,8 +49,8 @@ export default function DhpApplicationMixin(Base) {
return fp.browse(); return fp.browse();
} }
async _updateImage(path){ async _updateImage(path) {
await this.document.update({ "img": path }); await this.document.update({ img: path });
} }
_createDragDropHandlers() { _createDragDropHandlers() {
@ -69,5 +69,5 @@ export default function DhpApplicationMixin(Base) {
} }
_onDrop(event) {} _onDrop(event) {}
} };
} }

View file

@ -21,7 +21,6 @@
// return context; // return context;
// } // }
// async _handleAction(action, event, button) { // async _handleAction(action, event, button) {
// switch(action){ // switch(action){
// case 'attributeRoll': // case 'attributeRoll':
@ -39,36 +38,36 @@ const { ItemSheetV2 } = foundry.applications.sheets;
export default class DomainCardSheet extends DaggerheartSheet(ItemSheetV2) { export default class DomainCardSheet extends DaggerheartSheet(ItemSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: "daggerheart-domainCard", id: 'daggerheart-domainCard',
classes: ["daggerheart", "sheet", "domain-card"], classes: ['daggerheart', 'sheet', 'domain-card'],
position: { width: 600, height: 600 }, position: { width: 600, height: 600 },
actions: { actions: {
addAction: this.addAction, addAction: this.addAction,
editAction: this.editAction, editAction: this.editAction,
removeAction: this.removeAction, removeAction: this.removeAction
}, },
form: { form: {
handler: this.updateForm, handler: this.updateForm,
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false
}, }
}; };
static PARTS = { static PARTS = {
form: { form: {
id: "feature", id: 'feature',
template: "systems/daggerheart/templates/sheets/domainCard.hbs" template: 'systems/daggerheart/templates/sheets/domainCard.hbs'
}
} }
};
_getTabs() { _getTabs() {
const tabs = { const tabs = {
general: { active: true, cssClass: '', group: 'primary', id: 'general', icon: null, label: 'General' }, general: { active: true, cssClass: '', group: 'primary', id: 'general', icon: null, label: 'General' },
actions: { active: false, cssClass: '', group: 'primary', id: 'actions', icon: null, label: 'Actions' }, actions: { active: false, cssClass: '', group: 'primary', id: 'actions', icon: null, label: 'Actions' }
} };
for ( const v of Object.values(tabs) ) { for (const v of Object.values(tabs)) {
v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active; v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active;
v.cssClass = v.active ? "active" : ""; v.cssClass = v.active ? 'active' : '';
} }
return tabs; return tabs;
@ -83,28 +82,37 @@ export default class DomainCardSheet extends DaggerheartSheet(ItemSheetV2) {
} }
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
await this.document.update(formData.object) await this.document.update(formData.object);
this.render(); this.render();
} }
static async addAction(){ static async addAction() {
const actionIndexes = this.document.system.actions.map(x => x.id.split('-')[2]).sort((a, b) => a-b); const actionIndexes = this.document.system.actions.map(x => x.id.split('-')[2]).sort((a, b) => a - b);
const action = await new DaggerheartAction({ const action = await new DaggerheartAction(
id: `${this.document.id}-Action-${actionIndexes.length > 0 ? actionIndexes[0]+1 : 1}`, {
}, { id: `${this.document.id}-Action-${actionIndexes.length > 0 ? actionIndexes[0] + 1 : 1}`
parent: this.document, },
}); {
await this.document.update({ "system.actions": [...this.document.system.actions, action] }); parent: this.document
await (new DaggerheartActionConfig(this.document.system.actions[this.document.system.actions.length-1])).render(true); }
);
await this.document.update({ 'system.actions': [...this.document.system.actions, action] });
await new DaggerheartActionConfig(this.document.system.actions[this.document.system.actions.length - 1]).render(
true
);
} }
static async editAction(_, button){ static async editAction(_, button) {
const action = this.document.system.actions[button.dataset.index]; const action = this.document.system.actions[button.dataset.index];
await (new DaggerheartActionConfig(action)).render(true); await new DaggerheartActionConfig(action).render(true);
} }
static async removeAction(event, button){ static async removeAction(event, button) {
event.stopPropagation(); event.stopPropagation();
await this.document.update({ "system.actions": this.document.system.actions.filter((_, index) => index !== Number.parseInt(button.dataset.index)) }); await this.document.update({
'system.actions': this.document.system.actions.filter(
(_, index) => index !== Number.parseInt(button.dataset.index)
)
});
} }
} }

View file

@ -1,9 +1,8 @@
import DaggerheartSheet from "./daggerheart-sheet.mjs"; import DaggerheartSheet from './daggerheart-sheet.mjs';
const { DocumentSheetV2 } = foundry.applications.api; const { DocumentSheetV2 } = foundry.applications.api;
export default class DhpEnvironment extends DaggerheartSheet(DocumentSheetV2) { export default class DhpEnvironment extends DaggerheartSheet(DocumentSheetV2) {
constructor(options) {
constructor(options){
super(options); super(options);
this.editMode = false; this.editMode = false;
@ -11,10 +10,10 @@ export default class DhpEnvironment extends DaggerheartSheet(DocumentSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
classes: ["daggerheart", "sheet", "adversary", "environment"], classes: ['daggerheart', 'sheet', 'adversary', 'environment'],
position: { position: {
width: 600, width: 600,
height: "auto" height: 'auto'
}, },
actions: { actions: {
toggleSlider: this.toggleSlider, toggleSlider: this.toggleSlider,
@ -23,22 +22,22 @@ export default class DhpEnvironment extends DaggerheartSheet(DocumentSheetV2) {
removeFeature: this.removeFeature, removeFeature: this.removeFeature,
addTone: this.addTone, addTone: this.addTone,
removeTone: this.removeTone, removeTone: this.removeTone,
useFeature: this.useFeature, useFeature: this.useFeature
}, },
form: { form: {
handler: this._updateForm, handler: this._updateForm,
closeOnSubmit: false, closeOnSubmit: false,
submitOnChange: true, submitOnChange: true
} }
}; };
/** @override */ /** @override */
static PARTS = { static PARTS = {
form: { form: {
id: "form", id: 'form',
template: "systems/daggerheart/templates/sheets/environment.hbs" template: 'systems/daggerheart/templates/sheets/environment.hbs'
}
} }
};
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -56,7 +55,7 @@ export default class DhpEnvironment extends DaggerheartSheet(DocumentSheetV2) {
data: { data: {
type: game.i18n.localize(SYSTEM.ACTOR.adversaryTypes[this.document.system.type].name), type: game.i18n.localize(SYSTEM.ACTOR.adversaryTypes[this.document.system.type].name),
features: this.document.items.reduce((acc, x) => { features: this.document.items.reduce((acc, x) => {
if(x.type === 'feature'){ if (x.type === 'feature') {
const feature = x.toObject(); const feature = x.toObject();
acc.push({ acc.push({
...feature, ...feature,
@ -69,59 +68,65 @@ export default class DhpEnvironment extends DaggerheartSheet(DocumentSheetV2) {
} }
return acc; return acc;
}, []), }, [])
}, },
editMode: this.editMode, editMode: this.editMode,
config: SYSTEM, config: SYSTEM
} };
} }
static async _updateForm(event, _, formData) { static async _updateForm(event, _, formData) {
await this.document.update(formData.object) await this.document.update(formData.object);
this.render(); this.render();
} }
static toggleSlider(){ static toggleSlider() {
this.editMode = !this.editMode; this.editMode = !this.editMode;
this.render(); this.render();
} }
static async viewFeature(_, button){ static async viewFeature(_, button) {
const move = await fromUuid(button.dataset.feature); const move = await fromUuid(button.dataset.feature);
move.sheet.render(true); move.sheet.render(true);
} }
static async addFeature(){ static async addFeature() {
const result = await this.document.createEmbeddedDocuments("Item", [{ const result = await this.document.createEmbeddedDocuments('Item', [
{
name: game.i18n.localize('DAGGERHEART.Sheets.Environment.NewFeature'), name: game.i18n.localize('DAGGERHEART.Sheets.Environment.NewFeature'),
type: 'feature', type: 'feature'
}]); }
]);
await result[0].sheet.render(true); await result[0].sheet.render(true);
} }
static async removeFeature(_, button){ static async removeFeature(_, button) {
await this.document.items.find(x => x.uuid === button.dataset.feature).delete(); await this.document.items.find(x => x.uuid === button.dataset.feature).delete();
} }
static async addTone(){ static async addTone() {
await this.document.update({ "system.toneAndFeel": [...this.document.system.toneAndFeel, ''] }); await this.document.update({ 'system.toneAndFeel': [...this.document.system.toneAndFeel, ''] });
} }
static async removeTone(button){ static async removeTone(button) {
await this.document.update({ "system.toneAndFeel": this.document.system.toneAndFeel.filter((_, index) => index !== Number.parseInt(button.dataset.tone) )}); await this.document.update({
'system.toneAndFeel': this.document.system.toneAndFeel.filter(
(_, index) => index !== Number.parseInt(button.dataset.tone)
)
});
} }
static async useFeature(_, button){ static async useFeature(_, button) {
const item = this.document.items.find(x => x.uuid === button.dataset.feature); const item = this.document.items.find(x => x.uuid === button.dataset.feature);
const cls = getDocumentClass("ChatMessage"); const cls = getDocumentClass('ChatMessage');
const msg = new cls({ const msg = new cls({
user: game.user.id, user: game.user.id,
content: await renderTemplate("systems/daggerheart/templates/chat/ability-use.hbs", { content: await renderTemplate('systems/daggerheart/templates/chat/ability-use.hbs', {
title: game.i18n.format("DAGGERHEART.Chat.EnvironmentTitle", { actionType: button.dataset.actionType }), title: game.i18n.format('DAGGERHEART.Chat.EnvironmentTitle', { actionType: button.dataset.actionType }),
card: { name: item.name, img: item.img, description: item.system.description }, card: { name: item.name, img: item.img, description: item.system.description }
}), })
}); });
cls.create(msg.toObject()); cls.create(msg.toObject());

View file

@ -4,7 +4,7 @@ import DaggerheartSheet from './daggerheart-sheet.mjs';
const { ItemSheetV2 } = foundry.applications.sheets; const { ItemSheetV2 } = foundry.applications.sheets;
export default class FeatureSheet extends DaggerheartSheet(ItemSheetV2) { export default class FeatureSheet extends DaggerheartSheet(ItemSheetV2) {
constructor(options={}){ constructor(options = {}) {
super(options); super(options);
this.selectedEffectType = null; this.selectedEffectType = null;
@ -12,39 +12,39 @@ export default class FeatureSheet extends DaggerheartSheet(ItemSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: "daggerheart-feature", id: 'daggerheart-feature',
classes: ["daggerheart", "sheet", "feature"], classes: ['daggerheart', 'sheet', 'feature'],
position: { width: 600, height: 600 }, position: { width: 600, height: 600 },
actions: { actions: {
addEffect: this.addEffect, addEffect: this.addEffect,
removeEffect: this.removeEffect, removeEffect: this.removeEffect,
addAction: this.addAction, addAction: this.addAction,
editAction: this.editAction, editAction: this.editAction,
removeAction: this.removeAction, removeAction: this.removeAction
}, },
form: { form: {
handler: this.updateForm, handler: this.updateForm,
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false
}, }
}; };
static PARTS = { static PARTS = {
form: { form: {
id: "feature", id: 'feature',
template: "systems/daggerheart/templates/sheets/feature.hbs" template: 'systems/daggerheart/templates/sheets/feature.hbs'
}
} }
};
_getTabs() { _getTabs() {
const tabs = { const tabs = {
features: { active: true, cssClass: '', group: 'primary', id: 'features', icon: null, label: 'Features' }, features: { active: true, cssClass: '', group: 'primary', id: 'features', icon: null, label: 'Features' },
effects: { active: false, cssClass: '', group: 'primary', id: 'effects', icon: null, label: 'Effects' }, effects: { active: false, cssClass: '', group: 'primary', id: 'effects', icon: null, label: 'Effects' },
actions: { active: false, cssClass: '', group: 'primary', id: 'actions', icon: null, label: 'Actions' }, actions: { active: false, cssClass: '', group: 'primary', id: 'actions', icon: null, label: 'Actions' }
} };
for ( const v of Object.values(tabs) ) { for (const v of Object.values(tabs)) {
v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active; v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active;
v.cssClass = v.active ? "active" : ""; v.cssClass = v.active ? 'active' : '';
} }
return tabs; return tabs;
@ -52,14 +52,13 @@ export default class FeatureSheet extends DaggerheartSheet(ItemSheetV2) {
_attachPartListeners(partId, htmlElement, options) { _attachPartListeners(partId, htmlElement, options) {
super._attachPartListeners(partId, htmlElement, options); super._attachPartListeners(partId, htmlElement, options);
$(htmlElement).find(".effect-select").on("change", this.effectSelect.bind(this)); $(htmlElement).find('.effect-select').on('change', this.effectSelect.bind(this));
} }
async _prepareContext(_options) { async _prepareContext(_options) {
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
context.document = this.document; context.document = this.document;
context.tabs = this._getTabs(), (context.tabs = this._getTabs()), (context.generalConfig = SYSTEM.GENERAL);
context.generalConfig = SYSTEM.GENERAL;
context.itemConfig = SYSTEM.ITEM; context.itemConfig = SYSTEM.ITEM;
context.properties = SYSTEM.ACTOR.featureProperties; context.properties = SYSTEM.ACTOR.featureProperties;
context.dice = SYSTEM.GENERAL.diceTypes; context.dice = SYSTEM.GENERAL.diceTypes;
@ -70,17 +69,17 @@ export default class FeatureSheet extends DaggerheartSheet(ItemSheetV2) {
} }
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
await this.document.update(formData.object) await this.document.update(formData.object);
this.render(); this.render();
} }
effectSelect(event){ effectSelect(event) {
this.selectedEffectType = event.currentTarget.value; this.selectedEffectType = event.currentTarget.value;
this.render(true); this.render(true);
} }
static async addEffect(){ static async addEffect() {
if(!this.selectedEffectType) return; if (!this.selectedEffectType) return;
const { id, name, ...rest } = SYSTEM.EFFECTS.effectTypes[this.selectedEffectType]; const { id, name, ...rest } = SYSTEM.EFFECTS.effectTypes[this.selectedEffectType];
const update = { const update = {
@ -90,27 +89,33 @@ export default class FeatureSheet extends DaggerheartSheet(ItemSheetV2) {
...rest ...rest
} }
}; };
await this.item.update({ "system.effects": update }); await this.item.update({ 'system.effects': update });
} }
static async removeEffect(_, button){ static async removeEffect(_, button) {
const path = `system.effects.-=${button.dataset.effect}`; const path = `system.effects.-=${button.dataset.effect}`;
await this.item.update({ [path]: null }); await this.item.update({ [path]: null });
} }
static async addAction(){ static async addAction() {
const action = await new DaggerheartAction({}, {parent: this.document}); const action = await new DaggerheartAction({}, { parent: this.document });
await this.document.update({ "system.actions": [...this.document.system.actions, action] }); await this.document.update({ 'system.actions': [...this.document.system.actions, action] });
await (new DaggerheartActionConfig(this.document.system.actions[this.document.system.actions.length-1])).render(true); await new DaggerheartActionConfig(this.document.system.actions[this.document.system.actions.length - 1]).render(
true
);
} }
static async editAction(_, button){ static async editAction(_, button) {
const action = this.document.system.actions[button.dataset.index]; const action = this.document.system.actions[button.dataset.index];
await (new DaggerheartActionConfig(action)).render(true); await new DaggerheartActionConfig(action).render(true);
} }
static async removeAction(event, button){ static async removeAction(event, button) {
event.stopPropagation(); event.stopPropagation();
await this.document.update({ "system.actions": this.document.system.actions.filter((_, index) => index !== Number.parseInt(button.dataset.index)) }); await this.document.update({
'system.actions': this.document.system.actions.filter(
(_, index) => index !== Number.parseInt(button.dataset.index)
)
});
} }
} }

View file

@ -26,22 +26,22 @@ const { ItemSheetV2 } = foundry.applications.sheets;
export default class MiscellaneousSheet extends DaggerheartSheet(ItemSheetV2) { export default class MiscellaneousSheet extends DaggerheartSheet(ItemSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: "daggerheart-miscellaneous", id: 'daggerheart-miscellaneous',
classes: ["daggerheart", "sheet", "miscellaneous"], classes: ['daggerheart', 'sheet', 'miscellaneous'],
position: { width: 400 }, position: { width: 400 },
form: { form: {
handler: this.updateForm, handler: this.updateForm,
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false
}, }
}; };
static PARTS = { static PARTS = {
form: { form: {
id: "feature", id: 'feature',
template: "systems/daggerheart/templates/sheets/miscellaneous.hbs" template: 'systems/daggerheart/templates/sheets/miscellaneous.hbs'
}
} }
};
async _prepareContext(_options) { async _prepareContext(_options) {
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
@ -51,7 +51,7 @@ export default class MiscellaneousSheet extends DaggerheartSheet(ItemSheetV2) {
} }
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
await this.document.update(formData.object) await this.document.update(formData.object);
this.render(); this.render();
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -79,35 +79,63 @@ const { ItemSheetV2 } = foundry.applications.sheets;
export default class SubclassSheet extends DaggerheartSheet(ItemSheetV2) { export default class SubclassSheet extends DaggerheartSheet(ItemSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: "daggerheart-subclass", id: 'daggerheart-subclass',
classes: ["daggerheart", "sheet", "subclass"], classes: ['daggerheart', 'sheet', 'subclass'],
position: { width: 600 }, position: { width: 600 },
actions: { actions: {
editAbility: this.editAbility, editAbility: this.editAbility,
deleteFeatureAbility: this.deleteFeatureAbility, deleteFeatureAbility: this.deleteFeatureAbility
}, },
form: { form: {
handler: this.updateForm, handler: this.updateForm,
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false
}, },
dragDrop: [ dragDrop: [
{ dragSelector: null, dropSelector: '.foundation-tab' }, { dragSelector: null, dropSelector: '.foundation-tab' },
{ dragSelector: null, dropSelector: '.specialization-tab' }, { dragSelector: null, dropSelector: '.specialization-tab' },
{ dragSelector: null, dropSelector: '.mastery-tab' } { dragSelector: null, dropSelector: '.mastery-tab' }
], ]
}; };
_getTabs() { _getTabs() {
const tabs = { const tabs = {
general: { active: true, cssClass: '', group: 'primary', id: 'general', icon: null, label: game.i18n.localize('DAGGERHEART.Sheets.Subclass.Tabs.General') }, general: {
foundation: { active: false, cssClass: '', group: 'primary', id: 'foundation', icon: null, label: game.i18n.localize('DAGGERHEART.Sheets.Subclass.Tabs.Foundation') }, active: true,
specialization: { active: false, cssClass: '', group: 'primary', id: 'specialization', icon: null, label: game.i18n.localize('DAGGERHEART.Sheets.Subclass.Tabs.Specialization') }, cssClass: '',
mastery: { active: false, cssClass: '', group: 'primary', id: 'mastery', icon: null, label: game.i18n.localize('DAGGERHEART.Sheets.Subclass.Tabs.Mastery') }, group: 'primary',
id: 'general',
icon: null,
label: game.i18n.localize('DAGGERHEART.Sheets.Subclass.Tabs.General')
},
foundation: {
active: false,
cssClass: '',
group: 'primary',
id: 'foundation',
icon: null,
label: game.i18n.localize('DAGGERHEART.Sheets.Subclass.Tabs.Foundation')
},
specialization: {
active: false,
cssClass: '',
group: 'primary',
id: 'specialization',
icon: null,
label: game.i18n.localize('DAGGERHEART.Sheets.Subclass.Tabs.Specialization')
},
mastery: {
active: false,
cssClass: '',
group: 'primary',
id: 'mastery',
icon: null,
label: game.i18n.localize('DAGGERHEART.Sheets.Subclass.Tabs.Mastery')
} }
for ( const v of Object.values(tabs) ) { };
for (const v of Object.values(tabs)) {
v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active; v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active;
v.cssClass = v.active ? "active" : ""; v.cssClass = v.active ? 'active' : '';
} }
return tabs; return tabs;
@ -115,10 +143,10 @@ export default class SubclassSheet extends DaggerheartSheet(ItemSheetV2) {
static PARTS = { static PARTS = {
form: { form: {
id: "feature", id: 'feature',
template: "systems/daggerheart/templates/sheets/subclass.hbs" template: 'systems/daggerheart/templates/sheets/subclass.hbs'
}
} }
};
async _prepareContext(_options) { async _prepareContext(_options) {
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
@ -130,21 +158,23 @@ export default class SubclassSheet extends DaggerheartSheet(ItemSheetV2) {
} }
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
await this.document.update(formData.object) await this.document.update(formData.object);
this.render(); this.render();
} }
static async editAbility(_, button){ static async editAbility(_, button) {
const feature = await fromUuid(button.dataset.ability); const feature = await fromUuid(button.dataset.ability);
feature.sheet.render(true); feature.sheet.render(true);
} }
static async deleteFeatureAbility(event, button){ static async deleteFeatureAbility(event, button) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
const feature = button.dataset.feature; const feature = button.dataset.feature;
const newAbilities = this.document.system[`${feature}Feature`].abilities.filter(x => x.uuid !== button.dataset.ability); const newAbilities = this.document.system[`${feature}Feature`].abilities.filter(
x => x.uuid !== button.dataset.ability
);
const path = `system.${feature}Feature.abilities`; const path = `system.${feature}Feature.abilities`;
await this.document.update({ [path]: newAbilities }); await this.document.update({ [path]: newAbilities });
@ -153,15 +183,25 @@ export default class SubclassSheet extends DaggerheartSheet(ItemSheetV2) {
async _onDrop(event) { async _onDrop(event) {
const data = TextEditor.getDragEventData(event); const data = TextEditor.getDragEventData(event);
const item = await fromUuid(data.uuid); const item = await fromUuid(data.uuid);
if(item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.subclass.id) { if (item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.subclass.id) {
if(event.currentTarget.classList.contains('foundation-tab')){ if (event.currentTarget.classList.contains('foundation-tab')) {
await this.document.update({ "system.foundationFeature.abilities": [...this.document.system.foundationFeature.abilities, item.system] }); await this.document.update({
} 'system.foundationFeature.abilities': [
else if(event.currentTarget.classList.contains('specialization-tab')){ ...this.document.system.foundationFeature.abilities,
await this.document.update({ "system.specializationFeature.abilities": [...this.document.system.specializationFeature.abilities, data.system] }); item.system
} ]
else if(event.currentTarget.classList.contains('mastery-tab')){ });
await this.document.update({ "system.masteryFeature.abilities": [...this.document.system.masteryFeature.abilities, data.system] }); } else if (event.currentTarget.classList.contains('specialization-tab')) {
await this.document.update({
'system.specializationFeature.abilities': [
...this.document.system.specializationFeature.abilities,
data.system
]
});
} else if (event.currentTarget.classList.contains('mastery-tab')) {
await this.document.update({
'system.masteryFeature.abilities': [...this.document.system.masteryFeature.abilities, data.system]
});
} }
} }
} }

View file

@ -20,7 +20,6 @@
// return context; // return context;
// } // }
// async _handleAction(action, event, button) { // async _handleAction(action, event, button) {
// switch(action){ // switch(action){
// } // }
@ -33,22 +32,22 @@ const { ItemSheetV2 } = foundry.applications.sheets;
export default class WeaponSheet extends DaggerheartSheet(ItemSheetV2) { export default class WeaponSheet extends DaggerheartSheet(ItemSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: "daggerheart-weapon", id: 'daggerheart-weapon',
classes: ["daggerheart", "sheet", "weapon"], classes: ['daggerheart', 'sheet', 'weapon'],
position: { width: 400 }, position: { width: 400 },
form: { form: {
handler: this.updateForm, handler: this.updateForm,
submitOnChange: true, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false
}, }
}; };
static PARTS = { static PARTS = {
form: { form: {
id: "feature", id: 'feature',
template: "systems/daggerheart/templates/sheets/weapon.hbs" template: 'systems/daggerheart/templates/sheets/weapon.hbs'
}
} }
};
async _prepareContext(_options) { async _prepareContext(_options) {
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
@ -59,7 +58,7 @@ export default class WeaponSheet extends DaggerheartSheet(ItemSheetV2) {
} }
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
await this.document.update(formData.object) await this.document.update(formData.object);
this.render(); this.render();
} }
} }

View file

@ -1,17 +1,17 @@
export const actionTypes = { export const actionTypes = {
damage: { damage: {
id: "damage", id: 'damage',
name: "DAGGERHEART.Effects.Types.Health.Name" name: 'DAGGERHEART.Effects.Types.Health.Name'
}, }
} };
export const targetTypes = { export const targetTypes = {
self: { self: {
id: 'self', id: 'self',
label: 'Self', label: 'Self'
}, },
other: { other: {
id: 'other', id: 'other',
label: 'Other', label: 'Other'
}, }
} };

View file

@ -1,164 +1,191 @@
export const abilities = { export const abilities = {
agility: { agility: {
label: "DAGGERHEART.Abilities.Agility.Name", label: 'DAGGERHEART.Abilities.Agility.Name',
verbs: ["DAGGERHEART.Abilities.Agility.Verb.Sprint", "DAGGERHEART.Abilities.Agility.Verb.Leap", "DAGGERHEART.Abilities.Agility.Verb.Maneuver"], verbs: [
'DAGGERHEART.Abilities.Agility.Verb.Sprint',
'DAGGERHEART.Abilities.Agility.Verb.Leap',
'DAGGERHEART.Abilities.Agility.Verb.Maneuver'
]
}, },
strength: { strength: {
label: "DAGGERHEART.Abilities.Strength.Name", label: 'DAGGERHEART.Abilities.Strength.Name',
verbs: ["DAGGERHEART.Abilities.Strength.Verb.Lift", "DAGGERHEART.Abilities.Strength.Verb.Smash", "DAGGERHEART.Abilities.Strength.Verb.Grapple"], verbs: [
'DAGGERHEART.Abilities.Strength.Verb.Lift',
'DAGGERHEART.Abilities.Strength.Verb.Smash',
'DAGGERHEART.Abilities.Strength.Verb.Grapple'
]
}, },
finesse: { finesse: {
label: "DAGGERHEART.Abilities.Finesse.Name", label: 'DAGGERHEART.Abilities.Finesse.Name',
verbs: ["DAGGERHEART.Abilities.Finesse.Verb.Control", "DAGGERHEART.Abilities.Finesse.Verb.Hide", "DAGGERHEART.Abilities.Finesse.Verb.Tinker"], verbs: [
'DAGGERHEART.Abilities.Finesse.Verb.Control',
'DAGGERHEART.Abilities.Finesse.Verb.Hide',
'DAGGERHEART.Abilities.Finesse.Verb.Tinker'
]
}, },
instinct: { instinct: {
label: "DAGGERHEART.Abilities.Instinct.Name", label: 'DAGGERHEART.Abilities.Instinct.Name',
verbs: ["DAGGERHEART.Abilities.Instinct.Verb.Perceive", "DAGGERHEART.Abilities.Instinct.Verb.Sense", "DAGGERHEART.Abilities.Instinct.Verb.Navigate"], verbs: [
'DAGGERHEART.Abilities.Instinct.Verb.Perceive',
'DAGGERHEART.Abilities.Instinct.Verb.Sense',
'DAGGERHEART.Abilities.Instinct.Verb.Navigate'
]
}, },
presence: { presence: {
label: "DAGGERHEART.Abilities.Presence.Name", label: 'DAGGERHEART.Abilities.Presence.Name',
verbs: ["DAGGERHEART.Abilities.Presence.Verb.Charm", "DAGGERHEART.Abilities.Presence.Verb.Perform", "DAGGERHEART.Abilities.Presence.Verb.Deceive"], verbs: [
'DAGGERHEART.Abilities.Presence.Verb.Charm',
'DAGGERHEART.Abilities.Presence.Verb.Perform',
'DAGGERHEART.Abilities.Presence.Verb.Deceive'
]
}, },
knowledge: { knowledge: {
label: "DAGGERHEART.Abilities.Knowledge.Name", label: 'DAGGERHEART.Abilities.Knowledge.Name',
verbs: ["DAGGERHEART.Abilities.Knowledge.Verb.Recall", "DAGGERHEART.Abilities.Knowledge.Verb.Analyze", "DAGGERHEART.Abilities.Knowledge.Verb.Comprehend"], verbs: [
}, 'DAGGERHEART.Abilities.Knowledge.Verb.Recall',
'DAGGERHEART.Abilities.Knowledge.Verb.Analyze',
'DAGGERHEART.Abilities.Knowledge.Verb.Comprehend'
]
}
}; };
export const featureProperties = { export const featureProperties = {
agility: { agility: {
name: "DAGGERHEART.Abilities.Agility.Name", name: 'DAGGERHEART.Abilities.Agility.Name',
path: actor => actor.system.attributes.agility.data.value, path: actor => actor.system.attributes.agility.data.value
}, },
strength: { strength: {
name: "DAGGERHEART.Abilities.Strength.Name", name: 'DAGGERHEART.Abilities.Strength.Name',
path: actor => actor.system.attributes.strength.data.value, path: actor => actor.system.attributes.strength.data.value
}, },
finesse: { finesse: {
name: "DAGGERHEART.Abilities.Finesse.Name", name: 'DAGGERHEART.Abilities.Finesse.Name',
path: actor => actor.system.attributes.finesse.data.value, path: actor => actor.system.attributes.finesse.data.value
}, },
instinct: { instinct: {
name: "DAGGERHEART.Abilities.Instinct.Name", name: 'DAGGERHEART.Abilities.Instinct.Name',
path: actor => actor.system.attributes.instinct.data.value, path: actor => actor.system.attributes.instinct.data.value
}, },
presence: { presence: {
name: "DAGGERHEART.Abilities.Presence.Name", name: 'DAGGERHEART.Abilities.Presence.Name',
path: actor => actor.system.attributes.presence.data.value, path: actor => actor.system.attributes.presence.data.value
}, },
knowledge: { knowledge: {
name: "DAGGERHEART.Abilities.Knowledge.Name", name: 'DAGGERHEART.Abilities.Knowledge.Name',
path: actor => actor.system.attributes.knowledge.data.value, path: actor => actor.system.attributes.knowledge.data.value
}, },
spellcastingTrait: { spellcastingTrait: {
name: "DAGGERHEART.FeatureProperty.SpellcastingTrait", name: 'DAGGERHEART.FeatureProperty.SpellcastingTrait',
path: actor => actor.system.attributes[actor.system.subclass.system.spellcastingTrait].data.value, path: actor => actor.system.attributes[actor.system.subclass.system.spellcastingTrait].data.value
}, }
} };
export const adversaryTypes = { export const adversaryTypes = {
bruiser: { bruiser: {
name: "DAGGERHEART.Adversary.Bruiser.Name", name: 'DAGGERHEART.Adversary.Bruiser.Name',
description: "DAGGERHEART.Adversary.Bruiser.Description" description: 'DAGGERHEART.Adversary.Bruiser.Description'
}, },
horde: { horde: {
name: "DAGGERHEART.Adversary.Horde.Name", name: 'DAGGERHEART.Adversary.Horde.Name',
description: "DAGGERHEART.Adversary.Horde.Description" description: 'DAGGERHEART.Adversary.Horde.Description'
}, },
leader: { leader: {
name: "DAGGERHEART.Adversary.Leader.Name", name: 'DAGGERHEART.Adversary.Leader.Name',
description: "DAGGERHEART.Adversary.Leader.Description" description: 'DAGGERHEART.Adversary.Leader.Description'
}, },
minion: { minion: {
name: "DAGGERHEART.Adversary.Minion.Name", name: 'DAGGERHEART.Adversary.Minion.Name',
description: "DAGGERHEART.Adversary.Minion.Description" description: 'DAGGERHEART.Adversary.Minion.Description'
}, },
ranged: { ranged: {
name: "DAGGERHEART.Adversary.Ranged.Name", name: 'DAGGERHEART.Adversary.Ranged.Name',
description: "DAGGERHEART.Adversary.Ranged.Description" description: 'DAGGERHEART.Adversary.Ranged.Description'
}, },
skulker: { skulker: {
name: "DAGGERHEART.Adversary.Skulker.Name", name: 'DAGGERHEART.Adversary.Skulker.Name',
description: "DAGGERHEART.Adversary.Skulker.Description" description: 'DAGGERHEART.Adversary.Skulker.Description'
}, },
social: { social: {
name: "DAGGERHEART.Adversary.Social.Name", name: 'DAGGERHEART.Adversary.Social.Name',
description: "DAGGERHEART.Adversary.Social.Description" description: 'DAGGERHEART.Adversary.Social.Description'
}, },
solo: { solo: {
name: "DAGGERHEART.Adversary.Solo.Name", name: 'DAGGERHEART.Adversary.Solo.Name',
description: "DAGGERHEART.Adversary.Solo.Description" description: 'DAGGERHEART.Adversary.Solo.Description'
}, },
standard: { standard: {
name: "DAGGERHEART.Adversary.Standard.Name", name: 'DAGGERHEART.Adversary.Standard.Name',
description: "DAGGERHEART.Adversary.Standard.Description" description: 'DAGGERHEART.Adversary.Standard.Description'
}, },
support: { support: {
name: "DAGGERHEART.Adversary.Support.Name", name: 'DAGGERHEART.Adversary.Support.Name',
description: "DAGGERHEART.Adversary.Support.Description" description: 'DAGGERHEART.Adversary.Support.Description'
}, }
}; };
export const adversaryTraits = { export const adversaryTraits = {
relentless: { relentless: {
name: "DAGGERHEART.Adversary.Trait..Name", name: 'DAGGERHEART.Adversary.Trait..Name',
description: "DAGGERHEART.Adversary.Trait..Description", description: 'DAGGERHEART.Adversary.Trait..Description',
tip: "DAGGERHEART.Adversary.Trait..Tip", tip: 'DAGGERHEART.Adversary.Trait..Tip'
}, },
slow: { slow: {
name: "DAGGERHEART.Adversary.Trait..Name", name: 'DAGGERHEART.Adversary.Trait..Name',
description: "DAGGERHEART.Adversary.Trait..Description", description: 'DAGGERHEART.Adversary.Trait..Description',
tip: "DAGGERHEART.Adversary.Trait..Tip", tip: 'DAGGERHEART.Adversary.Trait..Tip'
}, },
minion: { minion: {
name: "DAGGERHEART.Adversary.Trait..Name", name: 'DAGGERHEART.Adversary.Trait..Name',
description: "DAGGERHEART.Adversary.Trait..Description", description: 'DAGGERHEART.Adversary.Trait..Description',
tip: "DAGGERHEART.Adversary.Trait..Tip", tip: 'DAGGERHEART.Adversary.Trait..Tip'
}, }
}; };
export const levelChoices = { export const levelChoices = {
attributes: { attributes: {
name: 'attributes', name: 'attributes',
title: '', title: '',
choices: [], choices: []
}, },
hitPointSlots: { hitPointSlots: {
name: 'hitPointSlots', name: 'hitPointSlots',
title: '', title: '',
choices: [], choices: []
}, },
stressSlots: { stressSlots: {
name: 'stressSlots', name: 'stressSlots',
title: '', title: '',
choices: [], choices: []
}, },
experiences: { experiences: {
name: 'experiences', name: 'experiences',
title: '', title: '',
choices: 'system.experiences', choices: 'system.experiences',
nrChoices: 2, nrChoices: 2
}, },
proficiency: { proficiency: {
name: 'proficiency', name: 'proficiency',
title: '', title: '',
choices: [], choices: []
}, },
armorOrEvasionSlot: { armorOrEvasionSlot: {
name: 'armorOrEvasionSlot', name: 'armorOrEvasionSlot',
title: 'Permanently add one Armor Slot or take +1 to your Evasion', title: 'Permanently add one Armor Slot or take +1 to your Evasion',
choices: [{ name: 'Armor Marks +1', path: 'armor' }, { name: 'Evasion +1', path: 'evasion' }], choices: [
nrChoices: 1, { name: 'Armor Marks +1', path: 'armor' },
{ name: 'Evasion +1', path: 'evasion' }
],
nrChoices: 1
}, },
majorDamageThreshold2: { majorDamageThreshold2: {
name: 'majorDamageThreshold2', name: 'majorDamageThreshold2',
title: '', title: '',
choices: [], choices: []
}, },
severeDamageThreshold2: { severeDamageThreshold2: {
name: 'severeDamageThreshold2', name: 'severeDamageThreshold2',
title: '', title: '',
choices: [], choices: []
}, },
// minorDamageThreshold2: { // minorDamageThreshold2: {
// name: 'minorDamageThreshold2', // name: 'minorDamageThreshold2',
@ -168,7 +195,7 @@ export const levelChoices = {
severeDamageThreshold3: { severeDamageThreshold3: {
name: 'severeDamageThreshold3', name: 'severeDamageThreshold3',
title: '', title: '',
choices: [], choices: []
}, },
// major2OrSevere4DamageThreshold: { // major2OrSevere4DamageThreshold: {
// name: 'major2OrSevere4DamageThreshold', // name: 'major2OrSevere4DamageThreshold',
@ -185,7 +212,7 @@ export const levelChoices = {
severeDamageThreshold4: { severeDamageThreshold4: {
name: 'severeDamageThreshold4', name: 'severeDamageThreshold4',
title: '', title: '',
choices: [], choices: []
}, },
// majorDamageThreshold1: { // majorDamageThreshold1: {
// name: 'majorDamageThreshold2', // name: 'majorDamageThreshold2',
@ -195,161 +222,161 @@ export const levelChoices = {
subclass: { subclass: {
name: 'subclass', name: 'subclass',
title: 'Select subclass to upgrade', title: 'Select subclass to upgrade',
choices: [], choices: []
}, },
multiclass: { multiclass: {
name: 'multiclass', name: 'multiclass',
title: '', title: '',
choices: [{}], choices: [{}]
} }
}; };
export const levelupData = { export const levelupData = {
tier1: { tier1: {
id: "2_4", id: '2_4',
tier: 1, tier: 1,
levels: [2,3,4], levels: [2, 3, 4],
label: 'DAGGERHEART.LevelUp.Tier1.Label', label: 'DAGGERHEART.LevelUp.Tier1.Label',
info: "DAGGERHEART.LevelUp.Tier1.InfoLabel", info: 'DAGGERHEART.LevelUp.Tier1.InfoLabel',
pretext: "DAGGERHEART.LevelUp.Tier1.Pretext", pretext: 'DAGGERHEART.LevelUp.Tier1.Pretext',
posttext: "DAGGERHEART.LevelUp.Tier1.Posttext", posttext: 'DAGGERHEART.LevelUp.Tier1.Posttext',
choices: { choices: {
[levelChoices.attributes.name]: { [levelChoices.attributes.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.Attributes", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.Attributes',
maxChoices: 3, maxChoices: 3
}, },
[levelChoices.hitPointSlots.name]: { [levelChoices.hitPointSlots.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.HitPointSlots", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.HitPointSlots',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.stressSlots.name]: { [levelChoices.stressSlots.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.StressSlots", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.StressSlots',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.experiences.name]: { [levelChoices.experiences.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.Experiences", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.Experiences',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.proficiency.name]: { [levelChoices.proficiency.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.Proficiency", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.Proficiency',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.armorOrEvasionSlot.name]: { [levelChoices.armorOrEvasionSlot.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.ArmorOrEvasionSlot", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.ArmorOrEvasionSlot',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.majorDamageThreshold2.name]: { [levelChoices.majorDamageThreshold2.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.MajorDamageThreshold2", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.MajorDamageThreshold2',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.severeDamageThreshold2.name]: { [levelChoices.severeDamageThreshold2.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.SevereDamageThreshold2", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.SevereDamageThreshold2',
maxChoices: 1, maxChoices: 1
} }
} }
}, },
tier2: { tier2: {
id: "5_7", id: '5_7',
tier: 2, tier: 2,
levels: [5,6,7], levels: [5, 6, 7],
label: 'DAGGERHEART.LevelUp.Tier2.Label', label: 'DAGGERHEART.LevelUp.Tier2.Label',
info: "DAGGERHEART.LevelUp.Tier2.InfoLabel", info: 'DAGGERHEART.LevelUp.Tier2.InfoLabel',
pretext: "DAGGERHEART.LevelUp.Tier2.Pretext", pretext: 'DAGGERHEART.LevelUp.Tier2.Pretext',
posttext: "DAGGERHEART.LevelUp.Tier2.Posttext", posttext: 'DAGGERHEART.LevelUp.Tier2.Posttext',
choices: { choices: {
[levelChoices.attributes.name]: { [levelChoices.attributes.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.Attributes", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.Attributes',
maxChoices: 3, maxChoices: 3
}, },
[levelChoices.hitPointSlots.name]: { [levelChoices.hitPointSlots.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.HitPointSlots", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.HitPointSlots',
maxChoices: 2, maxChoices: 2
}, },
[levelChoices.stressSlots.name]: { [levelChoices.stressSlots.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.StressSlots", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.StressSlots',
maxChoices: 2, maxChoices: 2
}, },
[levelChoices.experiences.name]: { [levelChoices.experiences.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.Experiences", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.Experiences',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.proficiency.name]: { [levelChoices.proficiency.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.Proficiency", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.Proficiency',
maxChoices: 2, maxChoices: 2
}, },
[levelChoices.armorOrEvasionSlot.name]: { [levelChoices.armorOrEvasionSlot.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.ArmorOrEvasionSlot", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.ArmorOrEvasionSlot',
maxChoices: 2, maxChoices: 2
}, },
[levelChoices.majorDamageThreshold2.name]: { [levelChoices.majorDamageThreshold2.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.MajorDamageThreshold2", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.MajorDamageThreshold2',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.severeDamageThreshold3.name]: { [levelChoices.severeDamageThreshold3.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.SevereDamageThreshold3", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.SevereDamageThreshold3',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.subclass.name]: { [levelChoices.subclass.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.Subclass", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.Subclass',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.multiclass.name]: { [levelChoices.multiclass.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.Multiclass", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.Multiclass',
maxChoices: 1, maxChoices: 1,
cost: 2, cost: 2
}, }
}, }
}, },
tier3: { tier3: {
id: "8_10", id: '8_10',
tier: 3, tier: 3,
levels: [8,9,10], levels: [8, 9, 10],
label: 'DAGGERHEART.LevelUp.Tier3.Label', label: 'DAGGERHEART.LevelUp.Tier3.Label',
info: "DAGGERHEART.LevelUp.Tier3.InfoLabel", info: 'DAGGERHEART.LevelUp.Tier3.InfoLabel',
pretext: "DAGGERHEART.LevelUp.Tier3.Pretext", pretext: 'DAGGERHEART.LevelUp.Tier3.Pretext',
posttext: "DAGGERHEART.LevelUp.Tier3.Posttext", posttext: 'DAGGERHEART.LevelUp.Tier3.Posttext',
choices: { choices: {
[levelChoices.attributes.name]: { [levelChoices.attributes.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.Attributes", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.Attributes',
maxChoices: 3, maxChoices: 3
}, },
[levelChoices.hitPointSlots.name]: { [levelChoices.hitPointSlots.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.HitPointSlots", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.HitPointSlots',
maxChoices: 2, maxChoices: 2
}, },
[levelChoices.stressSlots.name]: { [levelChoices.stressSlots.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.StressSlots", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.StressSlots',
maxChoices: 2, maxChoices: 2
}, },
[levelChoices.experiences.name]: { [levelChoices.experiences.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.Experiences", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.Experiences',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.proficiency.name]: { [levelChoices.proficiency.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.Proficiency", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.Proficiency',
maxChoices: 2, maxChoices: 2
}, },
[levelChoices.armorOrEvasionSlot.name]: { [levelChoices.armorOrEvasionSlot.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.ArmorOrEvasionSlot", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.ArmorOrEvasionSlot',
maxChoices: 2, maxChoices: 2
}, },
[levelChoices.majorDamageThreshold2.name]: { [levelChoices.majorDamageThreshold2.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.MajorDamageThreshold2", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.MajorDamageThreshold2',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.severeDamageThreshold4.name]: { [levelChoices.severeDamageThreshold4.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.SevereDamageThreshold4", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.SevereDamageThreshold4',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.subclass.name]: { [levelChoices.subclass.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.Subclass", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.Subclass',
maxChoices: 1, maxChoices: 1
}, },
[levelChoices.multiclass.name]: { [levelChoices.multiclass.name]: {
description: "DAGGERHEART.LevelUp.ChoiceDescriptions.Multiclass", description: 'DAGGERHEART.LevelUp.ChoiceDescriptions.Multiclass',
maxChoices: 1, maxChoices: 1,
cost: 2, cost: 2
}, }
}, }
} }
}; };

View file

@ -3,99 +3,99 @@ export const domains = {
id: 'arcana', id: 'arcana',
label: 'Arcana', label: 'Arcana',
src: 'icons/magic/symbols/circled-gem-pink.webp', src: 'icons/magic/symbols/circled-gem-pink.webp',
description: 'DAGGERHEART.Domains.Arcana', description: 'DAGGERHEART.Domains.Arcana'
}, },
blade: { blade: {
id: 'blade', id: 'blade',
label: 'Blade', label: 'Blade',
src: 'icons/weapons/swords/sword-broad-crystal-paired.webp', src: 'icons/weapons/swords/sword-broad-crystal-paired.webp',
description: 'DAGGERHEART.Domains.Blade', description: 'DAGGERHEART.Domains.Blade'
}, },
bone: { bone: {
id: 'bone', id: 'bone',
label: 'Bone', label: 'Bone',
src: 'icons/skills/wounds/bone-broken-marrow-red.webp', src: 'icons/skills/wounds/bone-broken-marrow-red.webp',
description: 'DAGGERHEART.Domains.Bone', description: 'DAGGERHEART.Domains.Bone'
}, },
codex: { codex: {
id: 'codex', id: 'codex',
label: 'Codex', label: 'Codex',
src: 'icons/sundries/books/book-embossed-jewel-gold-purple.webp', src: 'icons/sundries/books/book-embossed-jewel-gold-purple.webp',
description: 'DAGGERHEART.Domains.Codex', description: 'DAGGERHEART.Domains.Codex'
}, },
grace: { grace: {
id: 'grace', id: 'grace',
label: 'Grace', label: 'Grace',
src: 'icons/skills/movement/feet-winged-boots-glowing-yellow.webp', src: 'icons/skills/movement/feet-winged-boots-glowing-yellow.webp',
description: 'DAGGERHEART.Domains.Grace', description: 'DAGGERHEART.Domains.Grace'
}, },
midnight: { midnight: {
id: 'midnight', id: 'midnight',
label: 'Midnight', label: 'Midnight',
src: 'icons/environment/settlement/watchtower-castle-night.webp', src: 'icons/environment/settlement/watchtower-castle-night.webp',
background: 'systems/daggerheart/assets/backgrounds/MidnightBackground.webp', background: 'systems/daggerheart/assets/backgrounds/MidnightBackground.webp',
description: 'DAGGERHEART.Domains.Midnight', description: 'DAGGERHEART.Domains.Midnight'
}, },
sage: { sage: {
id: 'sage', id: 'sage',
label: 'Sage', label: 'Sage',
src: 'icons/sundries/misc/pipe-wooden-straight-brown.webp', src: 'icons/sundries/misc/pipe-wooden-straight-brown.webp',
description: 'DAGGERHEART.Domains.Sage', description: 'DAGGERHEART.Domains.Sage'
}, },
splendor: { splendor: {
id: 'splendor', id: 'splendor',
label: 'Splendor', label: 'Splendor',
src: 'icons/magic/control/control-influence-crown-gold.webp', src: 'icons/magic/control/control-influence-crown-gold.webp',
description: 'DAGGERHEART.Domains.Splendor', description: 'DAGGERHEART.Domains.Splendor'
}, },
valor: { valor: {
id: 'valor', id: 'valor',
label: 'Valor', label: 'Valor',
src: 'icons/magic/control/control-influence-rally-purple.webp', src: 'icons/magic/control/control-influence-rally-purple.webp',
description: 'DAGGERHEART.Domains.Valor', description: 'DAGGERHEART.Domains.Valor'
}, }
}; };
export const classDomainMap = { export const classDomainMap = {
rogue: [domains.midnight, domains.grace], rogue: [domains.midnight, domains.grace]
}; };
export const subclassMap = { export const subclassMap = {
syndicate: { syndicate: {
id: 'syndicate', id: 'syndicate',
label: 'Syndicate', label: 'Syndicate'
}, },
nightwalker: { nightwalker: {
id: 'nightwalker', id: 'nightwalker',
label: 'Nightwalker', label: 'Nightwalker'
}, }
}; };
export const classMap = { export const classMap = {
rogue: { rogue: {
label: "Rogue", label: 'Rogue',
subclasses: [subclassMap.syndicate.id, subclassMap.nightwalker.id], subclasses: [subclassMap.syndicate.id, subclassMap.nightwalker.id]
}, },
seraph: { seraph: {
label: "Seraph", label: 'Seraph',
subclasses: [] subclasses: []
}, }
}; };
export const cardTypes = { export const cardTypes = {
ability: { ability: {
id: 'ability', id: 'ability',
label: "DAGGERHEART.Domain.CardTypes.Ability", label: 'DAGGERHEART.Domain.CardTypes.Ability',
img: "", img: ''
}, },
spell: { spell: {
id: 'spell', id: 'spell',
label: "DAGGERHEART.Domain.CardTypes.Spell", label: 'DAGGERHEART.Domain.CardTypes.Spell',
img: "" img: ''
}, },
grimoire: { grimoire: {
id: 'grimoire', id: 'grimoire',
label: "DAGGERHEART.Domain.CardTypes.Grimoire", label: 'DAGGERHEART.Domain.CardTypes.Grimoire',
img: "" img: ''
} }
}; };

View file

@ -1,64 +1,64 @@
import { range } from "./generalConfig.mjs"; import { range } from './generalConfig.mjs';
export const valueTypes = { export const valueTypes = {
numberString: { numberString: {
id: 'numberString', id: 'numberString'
}, },
select: { select: {
id: 'select', id: 'select'
} }
} };
export const parseTypes = { export const parseTypes = {
string: { string: {
id: 'string', id: 'string'
}, },
number: { number: {
id: 'number', id: 'number'
}, }
} };
export const applyLocations = { export const applyLocations = {
attackRoll: { attackRoll: {
id: 'attackRoll', id: 'attackRoll',
name: "DAGGERHEART.Effects.ApplyLocations.AttackRoll.Name", name: 'DAGGERHEART.Effects.ApplyLocations.AttackRoll.Name'
}, },
damageRoll: { damageRoll: {
id: 'damageRoll', id: 'damageRoll',
name: "DAGGERHEART.Effects.ApplyLocations.DamageRoll.Name", name: 'DAGGERHEART.Effects.ApplyLocations.DamageRoll.Name'
} }
}; };
export const effectTypes = { export const effectTypes = {
health: { health: {
id: "health", id: 'health',
name: "DAGGERHEART.Effects.Types.Health.Name", name: 'DAGGERHEART.Effects.Types.Health.Name',
values: [], values: [],
valueType: valueTypes.numberString.id, valueType: valueTypes.numberString.id,
parseType: parseTypes.number.id, parseType: parseTypes.number.id
}, },
stress: { stress: {
id: "stress", id: 'stress',
name: "DAGGERHEART.Effects.Types.Stress.Name", name: 'DAGGERHEART.Effects.Types.Stress.Name',
valueType: valueTypes.numberString.id, valueType: valueTypes.numberString.id,
parseType: parseTypes.number.id, parseType: parseTypes.number.id
}, },
reach: { reach: {
id: "reach", id: 'reach',
name: "DAGGERHEART.Effects.Types.Reach.Name", name: 'DAGGERHEART.Effects.Types.Reach.Name',
valueType: valueTypes.select.id, valueType: valueTypes.select.id,
parseType: parseTypes.string.id, parseType: parseTypes.string.id,
options: Object.keys(range).map(x => ({ name: range[x].name, value: x })) options: Object.keys(range).map(x => ({ name: range[x].name, value: x }))
}, },
damage: { damage: {
id: "damage", id: 'damage',
name: "DAGGERHEART.Effects.Types.Damage.Name", name: 'DAGGERHEART.Effects.Types.Damage.Name',
valueType: valueTypes.numberString.id, valueType: valueTypes.numberString.id,
parseType: parseTypes.string.id, parseType: parseTypes.string.id,
appliesOn: applyLocations.damageRoll.id, appliesOn: applyLocations.damageRoll.id,
applyLocationChoices: { applyLocationChoices: {
[applyLocations.damageRoll.id]: applyLocations.damageRoll.name, [applyLocations.damageRoll.id]: applyLocations.damageRoll.name,
[applyLocations.attackRoll.id]: applyLocations.attackRoll.name, [applyLocations.attackRoll.id]: applyLocations.attackRoll.name
}, }
} }
}; };

View file

@ -1,170 +1,170 @@
export const range = { export const range = {
melee: { melee: {
label: "DAGGERHEART.Range.Melee.Name", label: 'DAGGERHEART.Range.Melee.Name',
description: "DAGGERHEART.Range.Melee.Description", description: 'DAGGERHEART.Range.Melee.Description',
distance: 1 distance: 1
}, },
veryClose: { veryClose: {
label: "DAGGERHEART.Range.VeryClose.Name", label: 'DAGGERHEART.Range.VeryClose.Name',
description: "DAGGERHEART.Range.VeryClose.Description", description: 'DAGGERHEART.Range.VeryClose.Description',
distance: 3 distance: 3
}, },
close: { close: {
label: "DAGGERHEART.Range.Close.Name", label: 'DAGGERHEART.Range.Close.Name',
description: "DAGGERHEART.Range.Close.Description", description: 'DAGGERHEART.Range.Close.Description',
distance: 10 distance: 10
}, },
far: { far: {
label: "DAGGERHEART.Range.Far.Name", label: 'DAGGERHEART.Range.Far.Name',
description: "DAGGERHEART.Range.Far.Description", description: 'DAGGERHEART.Range.Far.Description',
distance: 20 distance: 20
}, },
veryFar: { veryFar: {
label: "DAGGERHEART.Range.VeryFar.Name", label: 'DAGGERHEART.Range.VeryFar.Name',
description: "DAGGERHEART.Range.VeryFar.Description", description: 'DAGGERHEART.Range.VeryFar.Description',
distance: 30 distance: 30
} }
} };
export const burden = { export const burden = {
oneHanded: "DAGGERHEART.Burden.OneHanded", oneHanded: 'DAGGERHEART.Burden.OneHanded',
twoHanded: "DAGGERHEART.Burden.TwoHanded" twoHanded: 'DAGGERHEART.Burden.TwoHanded'
} };
export const damageTypes = { export const damageTypes = {
physical: { physical: {
id: 'physical', id: 'physical',
label: "DAGGERHEART.DamageType.Physical.Name", label: 'DAGGERHEART.DamageType.Physical.Name',
abbreviation: "DAGGERHEART.DamageType.Physical.Abbreviation", abbreviation: 'DAGGERHEART.DamageType.Physical.Abbreviation'
}, },
magical: { magical: {
id: 'magical', id: 'magical',
label: "DAGGERHEART.DamageType.Magical.Name", label: 'DAGGERHEART.DamageType.Magical.Name',
abbreviation: "DAGGERHEART.DamageType.Magical.Abbreviation", abbreviation: 'DAGGERHEART.DamageType.Magical.Abbreviation'
}, }
} };
export const healingTypes = { export const healingTypes = {
health: { health: {
id: 'health', id: 'health',
label: "DAGGERHEART.HealingType.HitPoints.Name", label: 'DAGGERHEART.HealingType.HitPoints.Name',
abbreviation: "DAGGERHEART.HealingType.HitPoints.Abbreviation" abbreviation: 'DAGGERHEART.HealingType.HitPoints.Abbreviation'
}, },
stress: { stress: {
id: 'stress', id: 'stress',
label: "DAGGERHEART.HealingType.Stress.Name", label: 'DAGGERHEART.HealingType.Stress.Name',
abbreviation: "DAGGERHEART.HealingType.Stress.Abbreviation" abbreviation: 'DAGGERHEART.HealingType.Stress.Abbreviation'
}, }
}; };
export const conditions = { export const conditions = {
vulnerable: { vulnerable: {
id: 'vulnerable', id: 'vulnerable',
name: "DAGGERHEART.Condition.Vulnerable.Name", name: 'DAGGERHEART.Condition.Vulnerable.Name',
icon: "icons/magic/control/silhouette-fall-slip-prone.webp", icon: 'icons/magic/control/silhouette-fall-slip-prone.webp',
description: "DAGGERHEART.Condition.Vulnerable.Description" description: 'DAGGERHEART.Condition.Vulnerable.Description'
}, },
hidden: { hidden: {
id: 'hidden', id: 'hidden',
name: "DAGGERHEART.Condition.Hidden.Name", name: 'DAGGERHEART.Condition.Hidden.Name',
icon: "icons/magic/perception/silhouette-stealth-shadow.webp", icon: 'icons/magic/perception/silhouette-stealth-shadow.webp',
description: "DAGGERHEART.Condition.Hidden.Description" description: 'DAGGERHEART.Condition.Hidden.Description'
}, },
restrained: { restrained: {
id: 'restrained', id: 'restrained',
name: "DAGGERHEART.Condition.Restrained.Name", name: 'DAGGERHEART.Condition.Restrained.Name',
icon: "icons/magic/control/debuff-chains-shackle-movement-red.webp", icon: 'icons/magic/control/debuff-chains-shackle-movement-red.webp',
description: "DAGGERHEART.Condition.Restrained.Description" description: 'DAGGERHEART.Condition.Restrained.Description'
}, }
} };
export const downtime = { export const downtime = {
shortRest: { shortRest: {
tendToWounds: { tendToWounds: {
id: "tendToWounds", id: 'tendToWounds',
name: "DAGGERHEART.Downtime.TendToWounds.Name", name: 'DAGGERHEART.Downtime.TendToWounds.Name',
img: "icons/magic/life/cross-worn-green.webp", img: 'icons/magic/life/cross-worn-green.webp',
description: "DAGGERHEART.Downtime.TendToWounds.Description", description: 'DAGGERHEART.Downtime.TendToWounds.Description'
}, },
clearStress: { clearStress: {
id: "clearStress", id: 'clearStress',
name: "DAGGERHEART.Downtime.ClearStress.Name", name: 'DAGGERHEART.Downtime.ClearStress.Name',
img: "icons/magic/perception/eye-ringed-green.webp", img: 'icons/magic/perception/eye-ringed-green.webp',
description: "DAGGERHEART.Downtime.ClearStress.Description", description: 'DAGGERHEART.Downtime.ClearStress.Description'
}, },
repairArmor: { repairArmor: {
id: "repairArmor", id: 'repairArmor',
name: "DAGGERHEART.Downtime.RepairArmor.Name", name: 'DAGGERHEART.Downtime.RepairArmor.Name',
img: "icons/skills/trades/smithing-anvil-silver-red.webp", img: 'icons/skills/trades/smithing-anvil-silver-red.webp',
description: "DAGGERHEART.Downtime.RepairArmor.Description", description: 'DAGGERHEART.Downtime.RepairArmor.Description'
}, },
prepare: { prepare: {
id: "prepare", id: 'prepare',
name: "DAGGERHEART.Downtime.Prepare.Name", name: 'DAGGERHEART.Downtime.Prepare.Name',
img: "icons/skills/trades/academics-merchant-scribe.webp", img: 'icons/skills/trades/academics-merchant-scribe.webp',
description: "DAGGERHEART.Downtime.Prepare.Description", description: 'DAGGERHEART.Downtime.Prepare.Description'
}, }
}, },
longRest: { longRest: {
tendToWounds: { tendToWounds: {
id: "tendToWounds", id: 'tendToWounds',
name: "DAGGERHEART.Downtime.TendToWounds.Name", name: 'DAGGERHEART.Downtime.TendToWounds.Name',
img: "icons/magic/life/cross-worn-green.webp", img: 'icons/magic/life/cross-worn-green.webp',
description: "DAGGERHEART.Downtime.TendToWounds.Description", description: 'DAGGERHEART.Downtime.TendToWounds.Description'
}, },
clearStress: { clearStress: {
id: "clearStress", id: 'clearStress',
name: "DAGGERHEART.Downtime.ClearStress.Name", name: 'DAGGERHEART.Downtime.ClearStress.Name',
img: "icons/magic/perception/eye-ringed-green.webp", img: 'icons/magic/perception/eye-ringed-green.webp',
description: "DAGGERHEART.Downtime.ClearStress.Description", description: 'DAGGERHEART.Downtime.ClearStress.Description'
}, },
repairArmor: { repairArmor: {
id: "repairArmor", id: 'repairArmor',
name: "DAGGERHEART.Downtime.RepairArmor.Name", name: 'DAGGERHEART.Downtime.RepairArmor.Name',
img: "icons/skills/trades/smithing-anvil-silver-red.webp", img: 'icons/skills/trades/smithing-anvil-silver-red.webp',
description: "DAGGERHEART.Downtime.RepairArmor.Description", description: 'DAGGERHEART.Downtime.RepairArmor.Description'
}, },
prepare: { prepare: {
id: "prepare", id: 'prepare',
name: "DAGGERHEART.Downtime.Prepare.Name", name: 'DAGGERHEART.Downtime.Prepare.Name',
img: "icons/skills/trades/academics-merchant-scribe.webp", img: 'icons/skills/trades/academics-merchant-scribe.webp',
description: "DAGGERHEART.Downtime.Prepare.Description", description: 'DAGGERHEART.Downtime.Prepare.Description'
}, },
workOnAProject: { workOnAProject: {
id: "workOnAProject", id: 'workOnAProject',
name: "DAGGERHEART.Downtime.WorkOnAProject.Name", name: 'DAGGERHEART.Downtime.WorkOnAProject.Name',
img: "icons/skills/social/thumbsup-approval-like.webp", img: 'icons/skills/social/thumbsup-approval-like.webp',
description: "DAGGERHEART.Downtime.WorkOnAProject.Description", description: 'DAGGERHEART.Downtime.WorkOnAProject.Description'
} }
}, },
custom: { custom: {
id: 'customActivity', id: 'customActivity',
name: "", name: '',
img: "icons/skills/trades/academics-investigation-puzzles.webp", img: 'icons/skills/trades/academics-investigation-puzzles.webp',
description: "", description: '',
namePlaceholder: "DAGGERHEART.Downtime.Custom.NamePlaceholder", namePlaceholder: 'DAGGERHEART.Downtime.Custom.NamePlaceholder',
placeholder: "DAGGERHEART.Downtime.Custom.Placeholder", placeholder: 'DAGGERHEART.Downtime.Custom.Placeholder'
} }
} };
export const deathMoves = { export const deathMoves = {
avoidDeath: { avoidDeath: {
id: "avoidDeath", id: 'avoidDeath',
name: "DAGGERHEART.DeathMoves.AvoidDeath.Name", name: 'DAGGERHEART.DeathMoves.AvoidDeath.Name',
img: "icons/magic/time/hourglass-yellow-green.webp", img: 'icons/magic/time/hourglass-yellow-green.webp',
description: "DAGGERHEART.DeathMoves.AvoidDeath.Description", description: 'DAGGERHEART.DeathMoves.AvoidDeath.Description'
}, },
riskItAll: { riskItAll: {
id: 'riskItAll', id: 'riskItAll',
name: "DAGGERHEART.DeathMoves.RiskItAll.Name", name: 'DAGGERHEART.DeathMoves.RiskItAll.Name',
img: "icons/sundries/gaming/dice-pair-white-green.webp", img: 'icons/sundries/gaming/dice-pair-white-green.webp',
description: "DAGGERHEART.DeathMoves.RiskItAll.Description", description: 'DAGGERHEART.DeathMoves.RiskItAll.Description'
}, },
blazeOfGlory: { blazeOfGlory: {
id: "blazeOfGlory", id: 'blazeOfGlory',
name: "DAGGERHEART.DeathMoves.BlazeOfGlory.Name", name: 'DAGGERHEART.DeathMoves.BlazeOfGlory.Name',
img: "icons/magic/life/heart-cross-strong-flame-purple-orange.webp", img: 'icons/magic/life/heart-cross-strong-flame-purple-orange.webp',
description: "DAGGERHEART.DeathMoves.BlazeOfGlory.Description", description: 'DAGGERHEART.DeathMoves.BlazeOfGlory.Description'
} }
}; };
@ -172,97 +172,97 @@ export const tiers = {
0: { 0: {
key: 0, key: 0,
id: 'tier0', id: 'tier0',
name: 'DAGGERHEART.General.Tier.0', name: 'DAGGERHEART.General.Tier.0'
}, },
1: { 1: {
key: 1, key: 1,
id: 'tier1', id: 'tier1',
name: 'DAGGERHEART.General.Tier.1', name: 'DAGGERHEART.General.Tier.1'
}, },
2: { 2: {
key: 2, key: 2,
id: 'tier2', id: 'tier2',
name: 'DAGGERHEART.General.Tier.2', name: 'DAGGERHEART.General.Tier.2'
}, },
3: { 3: {
key: 3, key: 3,
id: 'tier3', id: 'tier3',
name: 'DAGGERHEART.General.Tier.3', name: 'DAGGERHEART.General.Tier.3'
} }
}; };
export const objectTypes = { export const objectTypes = {
pc: { pc: {
name: "TYPES.Actor.pc", name: 'TYPES.Actor.pc'
}, },
npc: { npc: {
name: "TYPES.Actor.npc", name: 'TYPES.Actor.npc'
}, },
adversary: { adversary: {
name: "TYPES.Actor.adversary", name: 'TYPES.Actor.adversary'
}, },
ancestry: { ancestry: {
name: "TYPES.Item.ancestry", name: 'TYPES.Item.ancestry'
}, },
community: { community: {
name: "TYPES.Item.community", name: 'TYPES.Item.community'
}, },
class: { class: {
name: "TYPES.Item.class", name: 'TYPES.Item.class'
}, },
subclass: { subclass: {
name: "TYPES.Item.subclass", name: 'TYPES.Item.subclass'
}, },
feature: { feature: {
name: "TYPES.Item.feature", name: 'TYPES.Item.feature'
}, },
domainCard: { domainCard: {
name: "TYPES.Item.domainCard", name: 'TYPES.Item.domainCard'
}, },
consumable: { consumable: {
name: "TYPES.Item.consumable", name: 'TYPES.Item.consumable'
}, },
miscellaneous: { miscellaneous: {
name: "TYPES.Item.miscellaneous", name: 'TYPES.Item.miscellaneous'
}, },
weapon: { weapon: {
name: "TYPES.Item.weapon", name: 'TYPES.Item.weapon'
}, },
armor: { armor: {
name: "TYPES.Item.armor", name: 'TYPES.Item.armor'
} }
}; };
export const diceTypes = { export const diceTypes = {
d4: "d4", d4: 'd4',
d6: "d6", d6: 'd6',
d8: "d8", d8: 'd8',
d12: "d12", d12: 'd12',
d20: "d20" d20: 'd20'
}; };
export const refreshTypes = { export const refreshTypes = {
session: { session: {
id: 'session', id: 'session',
label: "DAGGERHEART.General.RefreshType.Session" label: 'DAGGERHEART.General.RefreshType.Session'
}, },
shortRest: { shortRest: {
id: 'shortRest', id: 'shortRest',
label: "DAGGERHEART.General.RefreshType.Shortrest", label: 'DAGGERHEART.General.RefreshType.Shortrest'
}, },
longRest: { longRest: {
id: 'longRest', id: 'longRest',
label: "DAGGERHEART.General.RefreshType.Longrest" label: 'DAGGERHEART.General.RefreshType.Longrest'
} }
} };
export const abilityCosts = { export const abilityCosts = {
hope: { hope: {
id: 'hope', id: 'hope',
label: 'Hope', label: 'Hope'
}, },
stress: { stress: {
id: 'stress', id: 'stress',
label: 'Stress', label: 'Stress'
} }
} };

View file

@ -1,351 +1,351 @@
export const armorFeatures = { export const armorFeatures = {
light: { light: {
label: "DAGGERHEART.ArmorFeature.Light.Name", label: 'DAGGERHEART.ArmorFeature.Light.Name',
description: "DAGGERHEART.ArmorFeature.Light.Description", description: 'DAGGERHEART.ArmorFeature.Light.Description'
}, },
heavy: { heavy: {
label: "DAGGERHEART.ArmorFeature.Heavy.Name", label: 'DAGGERHEART.ArmorFeature.Heavy.Name',
description: "DAGGERHEART.ArmorFeature.Heavy.Description", description: 'DAGGERHEART.ArmorFeature.Heavy.Description'
}, },
veryHeavy: { veryHeavy: {
label: "DAGGERHEART.ArmorFeature.VeryHeavy.Name", label: 'DAGGERHEART.ArmorFeature.VeryHeavy.Name',
description: "DAGGERHEART.ArmorFeature.VeryHeavy.Description", description: 'DAGGERHEART.ArmorFeature.VeryHeavy.Description'
}, },
reinforced: { reinforced: {
label: "DAGGERHEART.ArmorFeature.Reinforced.Name", label: 'DAGGERHEART.ArmorFeature.Reinforced.Name',
description: "DAGGERHEART.ArmorFeature.Reinforced.Description", description: 'DAGGERHEART.ArmorFeature.Reinforced.Description'
}, },
sturdy: { sturdy: {
label: "DAGGERHEART.ArmorFeature.Sturdy.Name", label: 'DAGGERHEART.ArmorFeature.Sturdy.Name',
description: "DAGGERHEART.ArmorFeature.Sturdy.Description", description: 'DAGGERHEART.ArmorFeature.Sturdy.Description'
}, },
warded: { warded: {
label: "DAGGERHEART.ArmorFeature.Warded.Name", label: 'DAGGERHEART.ArmorFeature.Warded.Name',
description: "DAGGERHEART.ArmorFeature.Warded.Description", description: 'DAGGERHEART.ArmorFeature.Warded.Description'
}, },
resistant: { resistant: {
label: "DAGGERHEART.ArmorFeature.Resistant.Name", label: 'DAGGERHEART.ArmorFeature.Resistant.Name',
description: "DAGGERHEART.ArmorFeature.Resistant.Description", description: 'DAGGERHEART.ArmorFeature.Resistant.Description'
}, },
quiet: { quiet: {
label: "DAGGERHEART.ArmorFeature.Quiet.Name", label: 'DAGGERHEART.ArmorFeature.Quiet.Name',
description: "DAGGERHEART.ArmorFeature.Quiet.Description", description: 'DAGGERHEART.ArmorFeature.Quiet.Description'
}, },
hopeful: { hopeful: {
label: "DAGGERHEART.ArmorFeature.Hopeful.Name", label: 'DAGGERHEART.ArmorFeature.Hopeful.Name',
description: "DAGGERHEART.ArmorFeature.Hopeful.Description", description: 'DAGGERHEART.ArmorFeature.Hopeful.Description'
}, },
impenetrable: { impenetrable: {
label: "DAGGERHEART.ArmorFeature.Impenetrable.Name", label: 'DAGGERHEART.ArmorFeature.Impenetrable.Name',
description: "DAGGERHEART.ArmorFeature.Impenetrable.Description", description: 'DAGGERHEART.ArmorFeature.Impenetrable.Description'
}, },
painful: { painful: {
label: "DAGGERHEART.ArmorFeature.Painful.Name", label: 'DAGGERHEART.ArmorFeature.Painful.Name',
description: "DAGGERHEART.ArmorFeature.Painful.Description", description: 'DAGGERHEART.ArmorFeature.Painful.Description'
}, },
gilded: { gilded: {
label: "DAGGERHEART.ArmorFeature.Gilded.Name", label: 'DAGGERHEART.ArmorFeature.Gilded.Name',
description: "DAGGERHEART.ArmorFeature.Gilded.Description", description: 'DAGGERHEART.ArmorFeature.Gilded.Description'
}, },
physical: { physical: {
label: "DAGGERHEART.ArmorFeature.Physical.Name", label: 'DAGGERHEART.ArmorFeature.Physical.Name',
description: "DAGGERHEART.ArmorFeature.Physical.Description", description: 'DAGGERHEART.ArmorFeature.Physical.Description'
}, },
magic: { magic: {
label: "DAGGERHEART.ArmorFeature.Magic.Name", label: 'DAGGERHEART.ArmorFeature.Magic.Name',
description: "DAGGERHEART.ArmorFeature.Magic.Description", description: 'DAGGERHEART.ArmorFeature.Magic.Description'
}, },
sharp: { sharp: {
label: "DAGGERHEART.ArmorFeature.Sharp.Name", label: 'DAGGERHEART.ArmorFeature.Sharp.Name',
description: "DAGGERHEART.ArmorFeature.Sharp.Description", description: 'DAGGERHEART.ArmorFeature.Sharp.Description'
}, },
burning: { burning: {
label: "DAGGERHEART.ArmorFeature.Burning.Name", label: 'DAGGERHEART.ArmorFeature.Burning.Name',
description: "DAGGERHEART.ArmorFeature.Burning.Description", description: 'DAGGERHEART.ArmorFeature.Burning.Description'
}, },
timeslowing: { timeslowing: {
label: "DAGGERHEART.ArmorFeature.Timeslowing.Name", label: 'DAGGERHEART.ArmorFeature.Timeslowing.Name',
description: "DAGGERHEART.ArmorFeature.Timeslowing.Description", description: 'DAGGERHEART.ArmorFeature.Timeslowing.Description'
}, },
truthseeking: { truthseeking: {
label: "DAGGERHEART.ArmorFeature.Truthseeking.Name", label: 'DAGGERHEART.ArmorFeature.Truthseeking.Name',
description: "DAGGERHEART.ArmorFeature.Truthseeking.Description", description: 'DAGGERHEART.ArmorFeature.Truthseeking.Description'
}, },
channeling: { channeling: {
label: "DAGGERHEART.ArmorFeature.Channeling.Name", label: 'DAGGERHEART.ArmorFeature.Channeling.Name',
description: "DAGGERHEART.ArmorFeature.Channeling.Description", description: 'DAGGERHEART.ArmorFeature.Channeling.Description'
}, },
difficult: { difficult: {
label: "DAGGERHEART.ArmorFeature.Difficult.Name", label: 'DAGGERHEART.ArmorFeature.Difficult.Name',
description: "DAGGERHEART.ArmorFeature.Difficult.Description", description: 'DAGGERHEART.ArmorFeature.Difficult.Description'
}, },
variable: { variable: {
label: "DAGGERHEART.ArmorFeature.Variable.Name", label: 'DAGGERHEART.ArmorFeature.Variable.Name',
description: "DAGGERHEART.ArmorFeature.Variable.Description", description: 'DAGGERHEART.ArmorFeature.Variable.Description'
}, }
}; };
export const weaponFeatures = { export const weaponFeatures = {
light: { light: {
label: "DAGGERHEART.WeaponFeature.Light.Name", label: 'DAGGERHEART.WeaponFeature.Light.Name',
description: "DAGGERHEART.WeaponFeature.Light.Description", description: 'DAGGERHEART.WeaponFeature.Light.Description'
}, },
heavy: { heavy: {
label: "DAGGERHEART.WeaponFeature.Heavy.Name", label: 'DAGGERHEART.WeaponFeature.Heavy.Name',
description: "DAGGERHEART.WeaponFeature.Heavy.Description", description: 'DAGGERHEART.WeaponFeature.Heavy.Description'
}, },
massive: { massive: {
label: "DAGGERHEART.WeaponFeature.Massive.Name", label: 'DAGGERHEART.WeaponFeature.Massive.Name',
description: "DAGGERHEART.WeaponFeature.Massive.Description", description: 'DAGGERHEART.WeaponFeature.Massive.Description'
}, },
reliable: { reliable: {
label: "DAGGERHEART.WeaponFeature.Reliable.Name", label: 'DAGGERHEART.WeaponFeature.Reliable.Name',
description: "DAGGERHEART.WeaponFeature.Reliable.Description", description: 'DAGGERHEART.WeaponFeature.Reliable.Description'
}, },
quick: { quick: {
label: "DAGGERHEART.WeaponFeature.Quick.Name", label: 'DAGGERHEART.WeaponFeature.Quick.Name',
description: "DAGGERHEART.WeaponFeature.Quick.Description", description: 'DAGGERHEART.WeaponFeature.Quick.Description'
}, },
cumbersome: { cumbersome: {
label: "DAGGERHEART.WeaponFeature.Cumbersome.Name", label: 'DAGGERHEART.WeaponFeature.Cumbersome.Name',
description: "DAGGERHEART.WeaponFeature.Cumbersome.Description", description: 'DAGGERHEART.WeaponFeature.Cumbersome.Description'
}, },
versatile: { versatile: {
label: "DAGGERHEART.WeaponFeature.Versatile.Name", label: 'DAGGERHEART.WeaponFeature.Versatile.Name',
description: "DAGGERHEART.WeaponFeature.Versatile.Description", description: 'DAGGERHEART.WeaponFeature.Versatile.Description',
override: { override: {
damage: "", damage: ''
} }
}, },
powerful: { powerful: {
label: "DAGGERHEART.WeaponFeature.Powerful.Name", label: 'DAGGERHEART.WeaponFeature.Powerful.Name',
description: "DAGGERHEART.WeaponFeature.Powerful.Description", description: 'DAGGERHEART.WeaponFeature.Powerful.Description'
}, },
scary: { scary: {
label: "DAGGERHEART.WeaponFeature.Scary.Name", label: 'DAGGERHEART.WeaponFeature.Scary.Name',
description: "DAGGERHEART.WeaponFeature.Scary.Description", description: 'DAGGERHEART.WeaponFeature.Scary.Description'
}, },
brutal: { brutal: {
label: "DAGGERHEART.WeaponFeature.Brutal.Name", label: 'DAGGERHEART.WeaponFeature.Brutal.Name',
description: "DAGGERHEART.WeaponFeature.Brutal.Description", description: 'DAGGERHEART.WeaponFeature.Brutal.Description'
}, },
reloading: { reloading: {
label: "DAGGERHEART.WeaponFeature.Reloading.Name", label: 'DAGGERHEART.WeaponFeature.Reloading.Name',
description: "DAGGERHEART.WeaponFeature.Reloading.Description", description: 'DAGGERHEART.WeaponFeature.Reloading.Description'
}, },
eruptive: { eruptive: {
label: "DAGGERHEART.WeaponFeature.Eruptive.Name", label: 'DAGGERHEART.WeaponFeature.Eruptive.Name',
description: "DAGGERHEART.WeaponFeature.Eruptive.Description", description: 'DAGGERHEART.WeaponFeature.Eruptive.Description'
}, },
persuasive: { persuasive: {
label: "DAGGERHEART.WeaponFeature.Persuasive.Name", label: 'DAGGERHEART.WeaponFeature.Persuasive.Name',
description: "DAGGERHEART.WeaponFeature.Persuasive.Description", description: 'DAGGERHEART.WeaponFeature.Persuasive.Description'
}, },
pompous: { pompous: {
label: "DAGGERHEART.WeaponFeature.Pompous.Name", label: 'DAGGERHEART.WeaponFeature.Pompous.Name',
description: "DAGGERHEART.WeaponFeature.Pompous.Description", description: 'DAGGERHEART.WeaponFeature.Pompous.Description'
}, },
invigorating: { invigorating: {
label: "DAGGERHEART.WeaponFeature.Invigorating.Name", label: 'DAGGERHEART.WeaponFeature.Invigorating.Name',
description: "DAGGERHEART.WeaponFeature.Invigorating.Description", description: 'DAGGERHEART.WeaponFeature.Invigorating.Description'
}, },
dense: { dense: {
label: "DAGGERHEART.WeaponFeature.Dense.Name", label: 'DAGGERHEART.WeaponFeature.Dense.Name',
description: "DAGGERHEART.WeaponFeature.Dense.Description", description: 'DAGGERHEART.WeaponFeature.Dense.Description'
}, },
soulswift: { soulswift: {
label: "DAGGERHEART.WeaponFeature.Soulswift.Name", label: 'DAGGERHEART.WeaponFeature.Soulswift.Name',
description: "DAGGERHEART.WeaponFeature.Soulswift.Description", description: 'DAGGERHEART.WeaponFeature.Soulswift.Description'
}, },
protective: { protective: {
label: "DAGGERHEART.WeaponFeature.Protective.Name", label: 'DAGGERHEART.WeaponFeature.Protective.Name',
description: "DAGGERHEART.WeaponFeature.Protective.Description", description: 'DAGGERHEART.WeaponFeature.Protective.Description'
}, },
devastating: { devastating: {
label: "DAGGERHEART.WeaponFeature.Devastating.Name", label: 'DAGGERHEART.WeaponFeature.Devastating.Name',
description: "DAGGERHEART.WeaponFeature.Devastating.Description", description: 'DAGGERHEART.WeaponFeature.Devastating.Description'
}, },
retractable: { retractable: {
label: "DAGGERHEART.WeaponFeature.Retractable.Name", label: 'DAGGERHEART.WeaponFeature.Retractable.Name',
description: "DAGGERHEART.WeaponFeature.Retractable.Description", description: 'DAGGERHEART.WeaponFeature.Retractable.Description'
}, },
burn: { burn: {
label: "DAGGERHEART.WeaponFeature.Burn.Name", label: 'DAGGERHEART.WeaponFeature.Burn.Name',
description: "DAGGERHEART.WeaponFeature.Burn.Description", description: 'DAGGERHEART.WeaponFeature.Burn.Description'
}, },
painful: { painful: {
label: "DAGGERHEART.WeaponFeature.Painful.Name", label: 'DAGGERHEART.WeaponFeature.Painful.Name',
description: "DAGGERHEART.WeaponFeature.Painful.Description", description: 'DAGGERHEART.WeaponFeature.Painful.Description'
}, },
otherwordly: { otherwordly: {
label: "DAGGERHEART.WeaponFeature.Otherwordly.Name", label: 'DAGGERHEART.WeaponFeature.Otherwordly.Name',
description: "DAGGERHEART.WeaponFeature.Otherwordly.Description", description: 'DAGGERHEART.WeaponFeature.Otherwordly.Description'
}, },
lucky: { lucky: {
label: "DAGGERHEART.WeaponFeature.Lucky.Name", label: 'DAGGERHEART.WeaponFeature.Lucky.Name',
description: "DAGGERHEART.WeaponFeature.Lucky.Description", description: 'DAGGERHEART.WeaponFeature.Lucky.Description'
}, },
selfCorrecting: { selfCorrecting: {
label: "DAGGERHEART.WeaponFeature.SelfCorrecting.Name", label: 'DAGGERHEART.WeaponFeature.SelfCorrecting.Name',
description: "DAGGERHEART.WeaponFeature.SelfCorrecting.Description", description: 'DAGGERHEART.WeaponFeature.SelfCorrecting.Description'
}, },
healing: { healing: {
label: "DAGGERHEART.WeaponFeature.Healing.Name", label: 'DAGGERHEART.WeaponFeature.Healing.Name',
description: "DAGGERHEART.WeaponFeature.Healing.Description", description: 'DAGGERHEART.WeaponFeature.Healing.Description'
}, },
timebender: { timebender: {
label: "DAGGERHEART.WeaponFeature.Timebender.Name", label: 'DAGGERHEART.WeaponFeature.Timebender.Name',
description: "DAGGERHEART.WeaponFeature.Timebender.Description", description: 'DAGGERHEART.WeaponFeature.Timebender.Description'
}, },
enchanted: { enchanted: {
label: "DAGGERHEART.WeaponFeature.Enchanted.Name", label: 'DAGGERHEART.WeaponFeature.Enchanted.Name',
description: "DAGGERHEART.WeaponFeature.Enchanted.Description", description: 'DAGGERHEART.WeaponFeature.Enchanted.Description'
}, },
serrated: { serrated: {
label: "DAGGERHEART.WeaponFeature.Serrated.Name", label: 'DAGGERHEART.WeaponFeature.Serrated.Name',
description: "DAGGERHEART.WeaponFeature.Serrated.Description", description: 'DAGGERHEART.WeaponFeature.Serrated.Description'
}, },
grappling: { grappling: {
label: "DAGGERHEART.WeaponFeature.Grappling.Name", label: 'DAGGERHEART.WeaponFeature.Grappling.Name',
description: "DAGGERHEART.WeaponFeature.Grappling.Description", description: 'DAGGERHEART.WeaponFeature.Grappling.Description'
}, },
long: { long: {
label: "DAGGERHEART.WeaponFeature.Long.Name", label: 'DAGGERHEART.WeaponFeature.Long.Name',
description: "DAGGERHEART.WeaponFeature.Long.Description", description: 'DAGGERHEART.WeaponFeature.Long.Description'
}, },
destructive: { destructive: {
label: "DAGGERHEART.WeaponFeature.Destructive.Name", label: 'DAGGERHEART.WeaponFeature.Destructive.Name',
description: "DAGGERHEART.WeaponFeature.Destructive.Description", description: 'DAGGERHEART.WeaponFeature.Destructive.Description'
}, },
concussive: { concussive: {
label: "DAGGERHEART.WeaponFeature.Concussive.Name", label: 'DAGGERHEART.WeaponFeature.Concussive.Name',
description: "DAGGERHEART.WeaponFeature.Concussive.Description", description: 'DAGGERHEART.WeaponFeature.Concussive.Description'
}, },
bouncing: { bouncing: {
label: "DAGGERHEART.WeaponFeature.Bouncing.Name", label: 'DAGGERHEART.WeaponFeature.Bouncing.Name',
description: "DAGGERHEART.WeaponFeature.Bouncing.Description", description: 'DAGGERHEART.WeaponFeature.Bouncing.Description'
}, },
penetrating: { penetrating: {
label: "DAGGERHEART.WeaponFeature.Penetrating.Name", label: 'DAGGERHEART.WeaponFeature.Penetrating.Name',
description: "DAGGERHEART.WeaponFeature.Penetrating.Description", description: 'DAGGERHEART.WeaponFeature.Penetrating.Description'
}, },
lifestealing: { lifestealing: {
label: "DAGGERHEART.WeaponFeature.Lifestealing.Name", label: 'DAGGERHEART.WeaponFeature.Lifestealing.Name',
description: "DAGGERHEART.WeaponFeature.Lifestealing.Description", description: 'DAGGERHEART.WeaponFeature.Lifestealing.Description'
}, },
greedy: { greedy: {
label: "DAGGERHEART.WeaponFeature.Greedy.Name", label: 'DAGGERHEART.WeaponFeature.Greedy.Name',
description: "DAGGERHEART.WeaponFeature.Greedy.Description", description: 'DAGGERHEART.WeaponFeature.Greedy.Description'
}, },
bonded: { bonded: {
label: "DAGGERHEART.WeaponFeature.Bonded.Name", label: 'DAGGERHEART.WeaponFeature.Bonded.Name',
description: "DAGGERHEART.WeaponFeature.Bonded.Description", description: 'DAGGERHEART.WeaponFeature.Bonded.Description'
}, },
barrier: { barrier: {
label: "DAGGERHEART.WeaponFeature.Barrier.Name", label: 'DAGGERHEART.WeaponFeature.Barrier.Name',
description: "DAGGERHEART.WeaponFeature.Barrier.Description", description: 'DAGGERHEART.WeaponFeature.Barrier.Description'
}, },
paired: { paired: {
label: "DAGGERHEART.WeaponFeature.Paired.Name", label: 'DAGGERHEART.WeaponFeature.Paired.Name',
description: "DAGGERHEART.WeaponFeature.Paired.Description", description: 'DAGGERHEART.WeaponFeature.Paired.Description'
}, },
whipcrack: { whipcrack: {
label: "DAGGERHEART.WeaponFeature.Whipcrack.Name", label: 'DAGGERHEART.WeaponFeature.Whipcrack.Name',
description: "DAGGERHEART.WeaponFeature.Whipcrack.Description", description: 'DAGGERHEART.WeaponFeature.Whipcrack.Description'
}, },
hook: { hook: {
label: "DAGGERHEART.WeaponFeature.Hook.Name", label: 'DAGGERHEART.WeaponFeature.Hook.Name',
description: "DAGGERHEART.WeaponFeature.Hook.Description", description: 'DAGGERHEART.WeaponFeature.Hook.Description'
}, },
doubleDuty: { doubleDuty: {
label: "DAGGERHEART.WeaponFeature.DoubleDuty.Name", label: 'DAGGERHEART.WeaponFeature.DoubleDuty.Name',
description: "DAGGERHEART.WeaponFeature.DoubleDuty.Description", description: 'DAGGERHEART.WeaponFeature.DoubleDuty.Description'
}, },
parry: { parry: {
label: "DAGGERHEART.WeaponFeature.Parry.Name", label: 'DAGGERHEART.WeaponFeature.Parry.Name',
description: "DAGGERHEART.WeaponFeature.Parry.Description", description: 'DAGGERHEART.WeaponFeature.Parry.Description'
}, },
retrieve: { retrieve: {
label: "DAGGERHEART.WeaponFeature.Retrieve.Name", label: 'DAGGERHEART.WeaponFeature.Retrieve.Name',
description: "DAGGERHEART.WeaponFeature.Retrieve.Description", description: 'DAGGERHEART.WeaponFeature.Retrieve.Description'
}, },
deflecting: { deflecting: {
label: "DAGGERHEART.WeaponFeature.Deflecting.Name", label: 'DAGGERHEART.WeaponFeature.Deflecting.Name',
description: "DAGGERHEART.WeaponFeature.Deflecting.Description", description: 'DAGGERHEART.WeaponFeature.Deflecting.Description'
}, },
chargedAttack: { chargedAttack: {
label: "DAGGERHEART.WeaponFeature.ChargedAttack.Name", label: 'DAGGERHEART.WeaponFeature.ChargedAttack.Name',
description: "DAGGERHEART.WeaponFeature.ChargedAttack.Description", description: 'DAGGERHEART.WeaponFeature.ChargedAttack.Description'
}, },
sheltering: { sheltering: {
label: "DAGGERHEART.WeaponFeature.Sheltering.Name", label: 'DAGGERHEART.WeaponFeature.Sheltering.Name',
description: "DAGGERHEART.WeaponFeature.Sheltering.Description", description: 'DAGGERHEART.WeaponFeature.Sheltering.Description'
}, },
doubledUp: { doubledUp: {
label: "DAGGERHEART.WeaponFeature.DoubledUp.Name", label: 'DAGGERHEART.WeaponFeature.DoubledUp.Name',
description: "DAGGERHEART.WeaponFeature.DoubledUp.Description", description: 'DAGGERHEART.WeaponFeature.DoubledUp.Description'
}, },
lockedOn: { lockedOn: {
label: "DAGGERHEART.WeaponFeature.LockedOn.Name", label: 'DAGGERHEART.WeaponFeature.LockedOn.Name',
description: "DAGGERHEART.WeaponFeature.LockedOn.Description", description: 'DAGGERHEART.WeaponFeature.LockedOn.Description'
}, }
}; };
export const featureTypes = { export const featureTypes = {
ancestry: { ancestry: {
id: "ancestry", id: 'ancestry',
label: "DAGGERHEART.Feature.Type.Ancestry" label: 'DAGGERHEART.Feature.Type.Ancestry'
}, },
community: { community: {
id: "community", id: 'community',
label: "DAGGERHEART.Feature.Type.Community" label: 'DAGGERHEART.Feature.Type.Community'
}, },
class: { class: {
id: "class", id: 'class',
label: "DAGGERHEART.Feature.Type.Class" label: 'DAGGERHEART.Feature.Type.Class'
}, },
subclass: { subclass: {
id: "subclass", id: 'subclass',
label: "DAGGERHEART.Feature.Type.Subclass" label: 'DAGGERHEART.Feature.Type.Subclass'
}, }
} };
export const valueTypes = { export const valueTypes = {
normal: { normal: {
id: 'normal', id: 'normal',
name: "DAGGERHEART.Feature.ValueType.Normal", name: 'DAGGERHEART.Feature.ValueType.Normal',
data: { data: {
value: 0, value: 0,
max: 0, max: 0
} }
}, },
input: { input: {
id: 'input', id: 'input',
name: "DAGGERHEART.Feature.ValueType.Input", name: 'DAGGERHEART.Feature.ValueType.Input',
data: { data: {
value: null, value: null
} }
}, },
dice: { dice: {
id: 'dice', id: 'dice',
name: "DAGGERHEART.Feature.ValueType.Dice", name: 'DAGGERHEART.Feature.ValueType.Dice',
data: { data: {
value: null, value: null
} }
} }
} };
export const actionTypes = { export const actionTypes = {
passive: { passive: {
id: "passive", id: 'passive',
label: "DAGGERHEART.ActionType.Passive" label: 'DAGGERHEART.ActionType.Passive'
}, },
action: { action: {
id: "action", id: 'action',
label: "DAGGERHEART.ActionType.Action" label: 'DAGGERHEART.ActionType.Action'
}, },
reaction: { reaction: {
id: "reaction", id: 'reaction',
label: "DAGGERHEART.ActionType.Reaction" label: 'DAGGERHEART.ActionType.Reaction'
} }
}; };

View file

@ -1,28 +1,28 @@
export const menu = { export const menu = {
Automation: { Automation: {
Name: "GameSettingsAutomation", Name: 'GameSettingsAutomation',
Icon: "fa-solid fa-robot", Icon: 'fa-solid fa-robot'
}, },
Homebrew: { Homebrew: {
Name: "GameSettingsHomebrew", Name: 'GameSettingsHomebrew',
Icon: "fa-solid fa-flask-vial", Icon: 'fa-solid fa-flask-vial'
}, },
Range: { Range: {
Name: "GameSettingsRange", Name: 'GameSettingsRange',
Icon: "fa-solid fa-ruler", Icon: 'fa-solid fa-ruler'
}, }
}; };
export const gameSettings = { export const gameSettings = {
Automation: { Automation: {
Hope: "AutomationHope", Hope: 'AutomationHope',
ActionPoints: "AutomationActionPoints", ActionPoints: 'AutomationActionPoints'
}, },
Resources: { Resources: {
Fear: "ResourcesFear" Fear: 'ResourcesFear'
}, },
General: { General: {
AbilityArray: "AbilityArray", AbilityArray: 'AbilityArray',
RangeMeasurement: "RangeMeasurement", RangeMeasurement: 'RangeMeasurement'
} }
} };

View file

@ -1,12 +1,12 @@
import * as GENERAL from './generalConfig.mjs'; import * as GENERAL from './generalConfig.mjs';
import * as DOMAIN from "./domainConfig.mjs"; import * as DOMAIN from './domainConfig.mjs';
import * as ACTOR from './actorConfig.mjs'; import * as ACTOR from './actorConfig.mjs';
import * as ITEM from './itemConfig.mjs'; import * as ITEM from './itemConfig.mjs';
import * as SETTINGS from './settingsConfig.mjs'; import * as SETTINGS from './settingsConfig.mjs';
import * as EFFECTS from './effectConfig.mjs'; import * as EFFECTS from './effectConfig.mjs';
import * as ACTIONS from './actionConfig.mjs'; import * as ACTIONS from './actionConfig.mjs';
export const SYSTEM_ID = "daggerheart"; export const SYSTEM_ID = 'daggerheart';
export const SYSTEM = { export const SYSTEM = {
id: SYSTEM_ID, id: SYSTEM_ID,
@ -16,5 +16,5 @@ export const SYSTEM = {
ITEM, ITEM,
SETTINGS, SETTINGS,
EFFECTS, EFFECTS,
ACTIONS, ACTIONS
}; };

View file

@ -7,24 +7,26 @@ export default class DhpAbilityUse extends foundry.abstract.TypeDataModel {
img: new fields.StringField({}), img: new fields.StringField({}),
name: new fields.StringField({}), name: new fields.StringField({}),
description: new fields.StringField({}), description: new fields.StringField({}),
actions: new fields.ArrayField(new fields.SchemaField({ actions: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}), name: new fields.StringField({}),
damage: new fields.SchemaField({ damage: new fields.SchemaField({
type: new fields.StringField({}), type: new fields.StringField({}),
value: new fields.StringField({}), value: new fields.StringField({})
}), }),
healing: new fields.SchemaField({ healing: new fields.SchemaField({
type: new fields.StringField({}), type: new fields.StringField({}),
value: new fields.StringField({}), value: new fields.StringField({})
}), }),
cost: new fields.SchemaField({ cost: new fields.SchemaField({
type: new fields.StringField({ nullable: true }), type: new fields.StringField({ nullable: true }),
value: new fields.NumberField({ nullable: true }), value: new fields.NumberField({ nullable: true })
}), }),
target: new fields.SchemaField({ target: new fields.SchemaField({
type: new fields.StringField({}), type: new fields.StringField({})
}), })
})), })
} )
};
} }
} }

View file

@ -6,30 +6,35 @@ export default class DaggerheartAction extends foundry.abstract.DataModel {
name: new fields.StringField({ initial: 'New Action' }), name: new fields.StringField({ initial: 'New Action' }),
damage: new fields.SchemaField({ damage: new fields.SchemaField({
type: new fields.StringField({ choices: SYSTEM.GENERAL.damageTypes, nullable: true, initial: null }), type: new fields.StringField({ choices: SYSTEM.GENERAL.damageTypes, nullable: true, initial: null }),
value: new fields.StringField({}), value: new fields.StringField({})
}), }),
healing: new fields.SchemaField({ healing: new fields.SchemaField({
type: new fields.StringField({ choices: SYSTEM.GENERAL.healingTypes, nullable: true, initial: null }), type: new fields.StringField({ choices: SYSTEM.GENERAL.healingTypes, nullable: true, initial: null }),
value: new fields.StringField(), value: new fields.StringField()
}), }),
conditions: new fields.ArrayField(new fields.SchemaField({ conditions: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField(), name: new fields.StringField(),
icon: new fields.StringField(), icon: new fields.StringField(),
description: new fields.StringField(), description: new fields.StringField()
})), })
),
cost: new fields.SchemaField({ cost: new fields.SchemaField({
type: new fields.StringField({ choices: SYSTEM.GENERAL.abilityCosts, nullable: true, initial: null }), type: new fields.StringField({ choices: SYSTEM.GENERAL.abilityCosts, nullable: true, initial: null }),
value: new fields.NumberField({ nullable: true, initial: null }), value: new fields.NumberField({ nullable: true, initial: null })
}), }),
target: new fields.SchemaField({ target: new fields.SchemaField({
type: new fields.StringField({ choices: SYSTEM.ACTIONS.targetTypes, initial: SYSTEM.ACTIONS.targetTypes.other.id }) type: new fields.StringField({
}), choices: SYSTEM.ACTIONS.targetTypes,
initial: SYSTEM.ACTIONS.targetTypes.other.id
})
})
// uses: new fields.SchemaField({ // uses: new fields.SchemaField({
// nr: new fields.StringField({}), // nr: new fields.StringField({}),
// refreshType: new fields.StringField({ choices: SYSTEM.GENERAL.refreshTypes, initial: SYSTEM.GENERAL.refreshTypes.session.id }), // refreshType: new fields.StringField({ choices: SYSTEM.GENERAL.refreshTypes, initial: SYSTEM.GENERAL.refreshTypes.session.id }),
// refreshed: new fields.BooleanField({ initial: true }), // refreshed: new fields.BooleanField({ initial: true }),
// }), // }),
} };
} }
use = async () => { use = async () => {

View file

@ -1,4 +1,4 @@
import { MappingField } from "./fields.mjs"; import { MappingField } from './fields.mjs';
export default class DhpAdversary extends foundry.abstract.TypeDataModel { export default class DhpAdversary extends foundry.abstract.TypeDataModel {
static defineSchema() { static defineSchema() {
@ -8,16 +8,20 @@ export default class DhpAdversary extends foundry.abstract.TypeDataModel {
health: new fields.SchemaField({ health: new fields.SchemaField({
value: new fields.NumberField({ initial: 0, integer: true }), value: new fields.NumberField({ initial: 0, integer: true }),
min: new fields.NumberField({ initial: 0, integer: true }), min: new fields.NumberField({ initial: 0, integer: true }),
max: new fields.NumberField({ initial: 0, integer: true }), max: new fields.NumberField({ initial: 0, integer: true })
}), }),
stress: new fields.SchemaField({ stress: new fields.SchemaField({
value: new fields.NumberField({ initial: 0, integer: true }), value: new fields.NumberField({ initial: 0, integer: true }),
min: new fields.NumberField({ initial: 0, integer: true }), min: new fields.NumberField({ initial: 0, integer: true }),
max: new fields.NumberField({ initial: 0, integer: true }), max: new fields.NumberField({ initial: 0, integer: true })
}), })
}), }),
tier: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.tiers), integer: false }), tier: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.tiers), integer: false }),
type: new fields.StringField({ choices: Object.keys(SYSTEM.ACTOR.adversaryTypes), integer: false, initial: Object.keys(SYSTEM.ACTOR.adversaryTypes).find(x => x === 'standard') }), type: new fields.StringField({
choices: Object.keys(SYSTEM.ACTOR.adversaryTypes),
integer: false,
initial: Object.keys(SYSTEM.ACTOR.adversaryTypes).find(x => x === 'standard')
}),
description: new fields.StringField({}), description: new fields.StringField({}),
motivesAndTactics: new fields.ArrayField(new fields.StringField({})), motivesAndTactics: new fields.ArrayField(new fields.StringField({})),
attackModifier: new fields.NumberField({ integer: true, nullabe: true, initial: null }), attackModifier: new fields.NumberField({ integer: true, nullabe: true, initial: null }),
@ -26,23 +30,25 @@ export default class DhpAdversary extends foundry.abstract.TypeDataModel {
range: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.range), integer: false }), range: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.range), integer: false }),
damage: new fields.SchemaField({ damage: new fields.SchemaField({
value: new fields.StringField({}), value: new fields.StringField({}),
type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false }), type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false })
}) })
}), }),
difficulty: new fields.NumberField({ initial: 1, integer: true }), difficulty: new fields.NumberField({ initial: 1, integer: true }),
damageThresholds: new fields.SchemaField({ damageThresholds: new fields.SchemaField({
minor: new fields.NumberField({ initial: 0, integer: true }), minor: new fields.NumberField({ initial: 0, integer: true }),
major: new fields.NumberField({ initial: 0, integer: true }), major: new fields.NumberField({ initial: 0, integer: true }),
severe: new fields.NumberField({ initial: 0, integer: true }), severe: new fields.NumberField({ initial: 0, integer: true })
}), }),
experiences: new fields.ArrayField(new fields.SchemaField({ experiences: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}), name: new fields.StringField({}),
value: new fields.NumberField({ integer: true, nullable: true, initial: null }), value: new fields.NumberField({ integer: true, nullable: true, initial: null })
})), })
} )
};
} }
get moves(){ get moves() {
return this.parent.items.filter(x => x.type === 'feature'); return this.parent.items.filter(x => x.type === 'feature');
} }
} }

View file

@ -5,41 +5,50 @@ export default class DhpAdversaryRoll extends foundry.abstract.TypeDataModel {
return { return {
roll: new fields.StringField({}), roll: new fields.StringField({}),
total: new fields.NumberField({ integer: true }), total: new fields.NumberField({ integer: true }),
modifiers: new fields.ArrayField(new fields.SchemaField({ modifiers: new fields.ArrayField(
new fields.SchemaField({
value: new fields.NumberField({ integer: true }), value: new fields.NumberField({ integer: true }),
label: new fields.StringField({}), label: new fields.StringField({}),
title: new fields.StringField({}), title: new fields.StringField({})
})), })
diceResults: new fields.ArrayField(new fields.SchemaField({ ),
diceResults: new fields.ArrayField(
new fields.SchemaField({
value: new fields.NumberField({ integer: true }), value: new fields.NumberField({ integer: true }),
discarded: new fields.BooleanField({ initial: false }), discarded: new fields.BooleanField({ initial: false })
})), })
targets: new fields.ArrayField(new fields.SchemaField({ ),
targets: new fields.ArrayField(
new fields.SchemaField({
id: new fields.StringField({}), id: new fields.StringField({}),
name: new fields.StringField({}), name: new fields.StringField({}),
img: new fields.StringField({}), img: new fields.StringField({}),
difficulty: new fields.NumberField({ integer: true, nullable: true }), difficulty: new fields.NumberField({ integer: true, nullable: true }),
evasion: new fields.NumberField({ integer: true }), evasion: new fields.NumberField({ integer: true }),
hit: new fields.BooleanField({ initial: false }), hit: new fields.BooleanField({ initial: false })
})), })
damage: new fields.SchemaField({ ),
damage: new fields.SchemaField(
{
value: new fields.StringField({}), value: new fields.StringField({}),
type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false }), type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false })
}, { nullable: true, initial: null }) },
} { nullable: true, initial: null }
)
};
} }
prepareDerivedData(){ prepareDerivedData() {
const diceKeys = Object.keys(this.diceResults); const diceKeys = Object.keys(this.diceResults);
const highestIndex = 0; const highestIndex = 0;
for(var index in diceKeys){ for (var index in diceKeys) {
const resultIndex = Number.parseInt(index); const resultIndex = Number.parseInt(index);
if(highestIndex === resultIndex) continue; if (highestIndex === resultIndex) continue;
const current = this.diceResults[resultIndex]; const current = this.diceResults[resultIndex];
const highest = this.diceResults[highestIndex]; const highest = this.diceResults[highestIndex];
if(current.value > highest.value) this.diceResults[highestIndex].discarded = true; if (current.value > highest.value) this.diceResults[highestIndex].discarded = true;
else this.diceResults[resultIndex].discarded = true; else this.diceResults[resultIndex].discarded = true;
} }

View file

@ -1,11 +1,11 @@
import featuresSchema from "./interface/featuresSchema.mjs"; import featuresSchema from './interface/featuresSchema.mjs';
export default class DhpAncestry extends foundry.abstract.TypeDataModel { export default class DhpAncestry extends foundry.abstract.TypeDataModel {
static defineSchema() { static defineSchema() {
const fields = foundry.data.fields; const fields = foundry.data.fields;
return { return {
description: new fields.HTMLField({}), description: new fields.HTMLField({}),
abilities: featuresSchema(), abilities: featuresSchema()
} };
} }
} }

View file

@ -6,24 +6,22 @@ export default class DhpArmor extends foundry.abstract.TypeDataModel {
feature: new fields.StringField({ feature: new fields.StringField({
choices: SYSTEM.ITEM.armorFeatures, choices: SYSTEM.ITEM.armorFeatures,
integer: false, integer: false,
blank: true, blank: true
}), }),
marks: new fields.SchemaField({ marks: new fields.SchemaField({
max: new fields.NumberField({ initial: 6, integer: true }), max: new fields.NumberField({ initial: 6, integer: true }),
value: new fields.NumberField({ initial: 0, integer: true }), value: new fields.NumberField({ initial: 0, integer: true })
}), }),
baseThresholds: new fields.SchemaField({ baseThresholds: new fields.SchemaField({
major: new fields.NumberField({ initial: 0, integer: true }), major: new fields.NumberField({ initial: 0, integer: true }),
severe: new fields.NumberField({ initial: 0, integer: true }), severe: new fields.NumberField({ initial: 0, integer: true })
}), }),
description: new fields.HTMLField({}), description: new fields.HTMLField({})
}; };
} }
get featureInfo() { get featureInfo() {
return this.feature return this.feature ? CONFIG.daggerheart.ITEM.armorFeatures[this.feature] : null;
? CONFIG.daggerheart.ITEM.armorFeatures[this.feature]
: null;
} }
prepareDerivedData() { prepareDerivedData() {

View file

@ -1,52 +1,67 @@
import { getTier } from "../helpers/utils.mjs"; import { getTier } from '../helpers/utils.mjs';
import DhpFeature from "./feature.mjs"; import DhpFeature from './feature.mjs';
export default class DhpClass extends foundry.abstract.TypeDataModel { export default class DhpClass extends foundry.abstract.TypeDataModel {
static defineSchema() { static defineSchema() {
const fields = foundry.data.fields; const fields = foundry.data.fields;
return { return {
domains: new fields.ArrayField(new fields.StringField({})), domains: new fields.ArrayField(new fields.StringField({})),
classItems: new fields.ArrayField(new fields.SchemaField({ classItems: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}), name: new fields.StringField({}),
img: new fields.StringField({}), img: new fields.StringField({}),
uuid: new fields.StringField({}), uuid: new fields.StringField({})
})), })
),
damageThresholds: new fields.SchemaField({ damageThresholds: new fields.SchemaField({
minor: new fields.NumberField({ initial: 0, integer: true }), minor: new fields.NumberField({ initial: 0, integer: true }),
major: new fields.NumberField({ initial: 0, integer: true }), major: new fields.NumberField({ initial: 0, integer: true }),
severe: new fields.NumberField({ initial: 0, integer: true }), severe: new fields.NumberField({ initial: 0, integer: true })
}), }),
evasion: new fields.NumberField({ initial: 0, integer: true}), evasion: new fields.NumberField({ initial: 0, integer: true }),
features: new fields.ArrayField(new fields.SchemaField({ features: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}), name: new fields.StringField({}),
img: new fields.StringField({}), img: new fields.StringField({}),
uuid: new fields.StringField({}), uuid: new fields.StringField({})
})), })
subclasses: new fields.ArrayField(new fields.SchemaField({ ),
subclasses: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}), name: new fields.StringField({}),
img: new fields.StringField({}), img: new fields.StringField({}),
uuid: new fields.StringField({}), uuid: new fields.StringField({})
})), })
),
inventory: new fields.SchemaField({ inventory: new fields.SchemaField({
take: new fields.ArrayField(new fields.SchemaField({ take: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}), name: new fields.StringField({}),
img: new fields.StringField({}), img: new fields.StringField({}),
uuid: new fields.StringField({}), uuid: new fields.StringField({})
})), })
choiceA: new fields.ArrayField(new fields.SchemaField({ ),
choiceA: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}), name: new fields.StringField({}),
img: new fields.StringField({}), img: new fields.StringField({}),
uuid: new fields.StringField({}), uuid: new fields.StringField({})
})), })
choiceB: new fields.ArrayField(new fields.SchemaField({ ),
choiceB: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}), name: new fields.StringField({}),
img: new fields.StringField({}), img: new fields.StringField({}),
uuid: new fields.StringField({}), uuid: new fields.StringField({})
})), })
extra: new fields.SchemaField({ ),
extra: new fields.SchemaField(
{
title: new fields.StringField({}), title: new fields.StringField({}),
description: new fields.StringField({}) description: new fields.StringField({})
}, { initial: null, nullable: true }), },
{ initial: null, nullable: true }
)
}), }),
characterGuide: new fields.SchemaField({ characterGuide: new fields.SchemaField({
suggestedTraits: new fields.SchemaField({ suggestedTraits: new fields.SchemaField({
@ -55,39 +70,48 @@ export default class DhpClass extends foundry.abstract.TypeDataModel {
finesse: new fields.NumberField({ initial: 0, integer: true }), finesse: new fields.NumberField({ initial: 0, integer: true }),
instinct: new fields.NumberField({ initial: 0, integer: true }), instinct: new fields.NumberField({ initial: 0, integer: true }),
presence: new fields.NumberField({ initial: 0, integer: true }), presence: new fields.NumberField({ initial: 0, integer: true }),
knowledge: new fields.NumberField({ initial: 0, integer: true }), knowledge: new fields.NumberField({ initial: 0, integer: true })
}), }),
suggestedPrimaryWeapon: new fields.SchemaField({ suggestedPrimaryWeapon: new fields.SchemaField(
{
name: new fields.StringField({}), name: new fields.StringField({}),
img: new fields.StringField({}), img: new fields.StringField({}),
uuid: new fields.StringField({}), uuid: new fields.StringField({})
}, { initial: null, nullable: true }), },
suggestedSecondaryWeapon: new fields.SchemaField({ { initial: null, nullable: true }
),
suggestedSecondaryWeapon: new fields.SchemaField(
{
name: new fields.StringField({}), name: new fields.StringField({}),
img: new fields.StringField({}), img: new fields.StringField({}),
uuid: new fields.StringField({}), uuid: new fields.StringField({})
}, { initial: null, nullable: true }), },
suggestedArmor: new fields.SchemaField({ { initial: null, nullable: true }
),
suggestedArmor: new fields.SchemaField(
{
name: new fields.StringField({}), name: new fields.StringField({}),
img: new fields.StringField({}), img: new fields.StringField({}),
uuid: new fields.StringField({}), uuid: new fields.StringField({})
}, { initial: null, nullable: true }), },
{ initial: null, nullable: true }
),
characterDescription: new fields.SchemaField({ characterDescription: new fields.SchemaField({
clothes: new fields.StringField({}), clothes: new fields.StringField({}),
eyes: new fields.StringField({}), eyes: new fields.StringField({}),
body: new fields.StringField({}), body: new fields.StringField({}),
color: new fields.StringField({}), color: new fields.StringField({}),
attitude: new fields.StringField({}), attitude: new fields.StringField({})
}), }),
backgroundQuestions: new fields.ArrayField(new fields.StringField({}), { initial: ['', '', ''] }), backgroundQuestions: new fields.ArrayField(new fields.StringField({}), { initial: ['', '', ''] }),
connections: new fields.ArrayField(new fields.StringField({}), { initial: ['', '' ,''] }), connections: new fields.ArrayField(new fields.StringField({}), { initial: ['', '', ''] })
}), }),
multiclass: new fields.NumberField({ initial: null, nullable: true, integer: true }), multiclass: new fields.NumberField({ initial: null, nullable: true, integer: true }),
description: new fields.HTMLField({}), description: new fields.HTMLField({})
} };
} }
get multiclassTier(){ get multiclassTier() {
return getTier(this.multiclass, true); return getTier(this.multiclass, true);
} }
} }

View file

@ -3,7 +3,7 @@ export default class DhpCombat extends foundry.abstract.TypeDataModel {
const fields = foundry.data.fields; const fields = foundry.data.fields;
return { return {
actions: new fields.NumberField({ initial: 0, integer: true }), actions: new fields.NumberField({ initial: 0, integer: true }),
activeCombatant: new fields.StringField({}), activeCombatant: new fields.StringField({})
} };
} }
} }

View file

@ -3,6 +3,6 @@ export default class DhpCombatant extends foundry.abstract.TypeDataModel {
const fields = foundry.data.fields; const fields = foundry.data.fields;
return { return {
active: new fields.BooleanField({ initial: false }) active: new fields.BooleanField({ initial: false })
} };
} }
} }

View file

@ -1,11 +1,11 @@
import featuresSchema from "./interface/featuresSchema.mjs"; import featuresSchema from './interface/featuresSchema.mjs';
export default class DhpCommunity extends foundry.abstract.TypeDataModel { export default class DhpCommunity extends foundry.abstract.TypeDataModel {
static defineSchema() { static defineSchema() {
const fields = foundry.data.fields; const fields = foundry.data.fields;
return { return {
description: new fields.HTMLField({}), description: new fields.HTMLField({}),
abilities: featuresSchema(), abilities: featuresSchema()
} };
} }
} }

View file

@ -4,7 +4,7 @@ export default class DhpConsumable extends foundry.abstract.TypeDataModel {
return { return {
description: new fields.HTMLField({}), description: new fields.HTMLField({}),
quantity: new fields.NumberField({ initial: 1, integer: true }), quantity: new fields.NumberField({ initial: 1, integer: true }),
consumeOnUse: new fields.BooleanField({ initial: false }), consumeOnUse: new fields.BooleanField({ initial: false })
} };
} }
} }

View file

@ -1,17 +1,23 @@
import DaggerheartAction from "./action.mjs"; import DaggerheartAction from './action.mjs';
export default class DhpDomainCard extends foundry.abstract.TypeDataModel { export default class DhpDomainCard extends foundry.abstract.TypeDataModel {
static defineSchema() { static defineSchema() {
const fields = foundry.data.fields; const fields = foundry.data.fields;
return { return {
domain: new fields.StringField({ choices: SYSTEM.DOMAIN.domains, integer: false }, { required: true, initial: [] }), domain: new fields.StringField(
{ choices: SYSTEM.DOMAIN.domains, integer: false },
{ required: true, initial: [] }
),
level: new fields.NumberField({ initial: 1, integer: true }), level: new fields.NumberField({ initial: 1, integer: true }),
recallCost: new fields.NumberField({ initial: 0, integer: true }), recallCost: new fields.NumberField({ initial: 0, integer: true }),
type: new fields.StringField({ choices: SYSTEM.DOMAIN.cardTypes, integer: false }, { required: true, initial: [] }), type: new fields.StringField(
{ choices: SYSTEM.DOMAIN.cardTypes, integer: false },
{ required: true, initial: [] }
),
foundation: new fields.BooleanField({ initial: false }), foundation: new fields.BooleanField({ initial: false }),
effect: new fields.HTMLField({}), effect: new fields.HTMLField({}),
inVault: new fields.BooleanField({ initial: false }), inVault: new fields.BooleanField({ initial: false }),
actions: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartAction)), actions: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartAction))
} };
} }
} }

View file

@ -1,60 +1,78 @@
const fields = foundry.data.fields; const fields = foundry.data.fields;
const diceField = () => new fields.SchemaField({ const diceField = () =>
new fields.SchemaField({
dice: new fields.StringField({}), dice: new fields.StringField({}),
value: new fields.NumberField({ integer: true}), value: new fields.NumberField({ integer: true })
}); });
export default class DhpDualityRoll extends foundry.abstract.TypeDataModel { export default class DhpDualityRoll extends foundry.abstract.TypeDataModel {
static defineSchema() { static defineSchema() {
return { return {
roll: new fields.StringField({}), roll: new fields.StringField({}),
modifiers: new fields.ArrayField(new fields.SchemaField({ modifiers: new fields.ArrayField(
new fields.SchemaField({
value: new fields.NumberField({ integer: true }), value: new fields.NumberField({ integer: true }),
label: new fields.StringField({}), label: new fields.StringField({}),
title: new fields.StringField({}), title: new fields.StringField({})
})), })
),
hope: diceField(), hope: diceField(),
fear: diceField(), fear: diceField(),
advantage: diceField(), advantage: diceField(),
disadvantage: diceField(), disadvantage: diceField(),
advantageSelected: new fields.NumberField({ initial: 0 }), advantageSelected: new fields.NumberField({ initial: 0 }),
targets: new fields.ArrayField(new fields.SchemaField({ targets: new fields.ArrayField(
new fields.SchemaField({
id: new fields.StringField({}), id: new fields.StringField({}),
name: new fields.StringField({}), name: new fields.StringField({}),
img: new fields.StringField({}), img: new fields.StringField({}),
difficulty: new fields.NumberField({ integer: true, nullable: true }), difficulty: new fields.NumberField({ integer: true, nullable: true }),
evasion: new fields.NumberField({ integer: true }), evasion: new fields.NumberField({ integer: true }),
hit: new fields.BooleanField({ initial: false }), hit: new fields.BooleanField({ initial: false })
})), })
),
damage: new fields.SchemaField({ damage: new fields.SchemaField({
value: new fields.StringField({}), value: new fields.StringField({}),
type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false }), type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false }),
bonusDamage: new fields.ArrayField(new fields.SchemaField({ bonusDamage: new fields.ArrayField(
new fields.SchemaField({
value: new fields.StringField({}), value: new fields.StringField({}),
type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false }), type: new fields.StringField({
choices: Object.keys(SYSTEM.GENERAL.damageTypes),
integer: false
}),
initiallySelected: new fields.BooleanField(), initiallySelected: new fields.BooleanField(),
appliesOn: new fields.StringField({ choices: Object.keys(SYSTEM.EFFECTS.applyLocations) }, { nullable: true, initial: null }), appliesOn: new fields.StringField(
{ choices: Object.keys(SYSTEM.EFFECTS.applyLocations) },
{ nullable: true, initial: null }
),
description: new fields.StringField({}), description: new fields.StringField({}),
hopeIncrease: new fields.StringField({ nullable: true }) hopeIncrease: new fields.StringField({ nullable: true })
}), { nullable: true, initial: null }) }),
{ nullable: true, initial: null }
)
}) })
} };
} }
get total() { get total() {
const modifiers = this.modifiers.reduce((acc, x) => acc+x.value, 0); const modifiers = this.modifiers.reduce((acc, x) => acc + x.value, 0);
const advantage = this.advantage.value ?? this.disadvantage.value ? -this.disadvantage.value : 0; const advantage = (this.advantage.value ?? this.disadvantage.value) ? -this.disadvantage.value : 0;
return this.hope.value + this.fear.value + advantage + modifiers; return this.hope.value + this.fear.value + advantage + modifiers;
} }
get totalLabel() { get totalLabel() {
const label = this.hope.value > this.fear.value ? "DAGGERHEART.General.Hope" : this.fear.value > this.hope.value ? "DAGGERHEART.General.Fear" : "DAGGERHEART.General.CriticalSuccess"; const label =
this.hope.value > this.fear.value
? 'DAGGERHEART.General.Hope'
: this.fear.value > this.hope.value
? 'DAGGERHEART.General.Fear'
: 'DAGGERHEART.General.CriticalSuccess';
return game.i18n.localize(label); return game.i18n.localize(label);
} }
prepareDerivedData(){ prepareDerivedData() {
const total = this.total; const total = this.total;
this.targets.forEach(target => { this.targets.forEach(target => {

View file

@ -2,19 +2,21 @@ export default class DhpEnvironment extends foundry.abstract.TypeDataModel {
static defineSchema() { static defineSchema() {
const fields = foundry.data.fields; const fields = foundry.data.fields;
return { return {
resources: new fields.SchemaField({ resources: new fields.SchemaField({}),
}),
tier: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.tiers), integer: false }), tier: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.tiers), integer: false }),
type: new fields.StringField({ choices: Object.keys(SYSTEM.ACTOR.adversaryTypes), integer: false, initial: Object.keys(SYSTEM.ACTOR.adversaryTypes).find(x => x === 'standard') }), type: new fields.StringField({
choices: Object.keys(SYSTEM.ACTOR.adversaryTypes),
integer: false,
initial: Object.keys(SYSTEM.ACTOR.adversaryTypes).find(x => x === 'standard')
}),
description: new fields.StringField({}), description: new fields.StringField({}),
toneAndFeel: new fields.StringField({}), toneAndFeel: new fields.StringField({}),
difficulty: new fields.NumberField({ initial: 1, integer: true }), difficulty: new fields.NumberField({ initial: 1, integer: true }),
potentialAdversaries: new fields.StringField({}), potentialAdversaries: new fields.StringField({})
} };
} }
get features(){ get features() {
return this.parent.items.filter(x => x.type === 'feature'); return this.parent.items.filter(x => x.type === 'feature');
} }
} }

View file

@ -1,70 +1,99 @@
import { getTier } from "../helpers/utils.mjs"; import { getTier } from '../helpers/utils.mjs';
import DaggerheartAction from "./action.mjs"; import DaggerheartAction from './action.mjs';
import { MappingField } from "./fields.mjs"; import { MappingField } from './fields.mjs';
import DhpEffect from "./interface/effects.mjs"; import DhpEffect from './interface/effects.mjs';
export default class DhpFeature extends DhpEffect { export default class DhpFeature extends DhpEffect {
static defineSchema() { static defineSchema() {
const fields = foundry.data.fields; const fields = foundry.data.fields;
return foundry.utils.mergeObject({}, { return foundry.utils.mergeObject(
{},
{
type: new fields.StringField({ choices: SYSTEM.ITEM.featureTypes }), type: new fields.StringField({ choices: SYSTEM.ITEM.featureTypes }),
actionType: new fields.StringField({ choices: SYSTEM.ITEM.actionTypes, initial: SYSTEM.ITEM.actionTypes.passive.id }), actionType: new fields.StringField({
choices: SYSTEM.ITEM.actionTypes,
initial: SYSTEM.ITEM.actionTypes.passive.id
}),
featureType: new fields.SchemaField({ featureType: new fields.SchemaField({
type: new fields.StringField({ choices: SYSTEM.ITEM.valueTypes, initial: Object.keys(SYSTEM.ITEM.valueTypes).find(x => x === 'normal') }), type: new fields.StringField({
choices: SYSTEM.ITEM.valueTypes,
initial: Object.keys(SYSTEM.ITEM.valueTypes).find(x => x === 'normal')
}),
data: new fields.SchemaField({ data: new fields.SchemaField({
value: new fields.StringField({}), value: new fields.StringField({}),
property: new fields.StringField({ choices: SYSTEM.ACTOR.featureProperties, initial: Object.keys(SYSTEM.ACTOR.featureProperties).find(x => x === 'spellcastingTrait') }), property: new fields.StringField({
choices: SYSTEM.ACTOR.featureProperties,
initial: Object.keys(SYSTEM.ACTOR.featureProperties).find(x => x === 'spellcastingTrait')
}),
max: new fields.NumberField({ initial: 1, integer: true }), max: new fields.NumberField({ initial: 1, integer: true }),
numbers: new MappingField(new fields.SchemaField({ numbers: new MappingField(
new fields.SchemaField({
value: new fields.NumberField({ integer: true }), value: new fields.NumberField({ integer: true }),
used: new fields.BooleanField({ initial: false }), used: new fields.BooleanField({ initial: false })
})), })
)
})
}), }),
}), refreshData: new fields.SchemaField(
refreshData: new fields.SchemaField({ {
type: new fields.StringField({ choices: SYSTEM.GENERAL.refreshTypes }), type: new fields.StringField({ choices: SYSTEM.GENERAL.refreshTypes }),
uses: new fields.NumberField({ initial: 1, integer: true }), uses: new fields.NumberField({ initial: 1, integer: true }),
refreshed: new fields.BooleanField({ initial: true }) refreshed: new fields.BooleanField({ initial: true })
}, { nullable: true, initial: null }), },
{ nullable: true, initial: null }
),
multiclass: new fields.NumberField({ initial: null, nullable: true, integer: true }), multiclass: new fields.NumberField({ initial: null, nullable: true, integer: true }),
disabled: new fields.BooleanField({ initial: false }), disabled: new fields.BooleanField({ initial: false }),
description: new fields.HTMLField({}), description: new fields.HTMLField({}),
effects: new MappingField(new fields.SchemaField({ effects: new MappingField(
new fields.SchemaField({
type: new fields.StringField({ choices: SYSTEM.EFFECTS.effectTypes }), type: new fields.StringField({ choices: SYSTEM.EFFECTS.effectTypes }),
valueType: new fields.StringField({ choices: SYSTEM.EFFECTS.valueTypes }), valueType: new fields.StringField({ choices: SYSTEM.EFFECTS.valueTypes }),
parseType: new fields.StringField({ choices: SYSTEM.EFFECTS.parseTypes }), parseType: new fields.StringField({ choices: SYSTEM.EFFECTS.parseTypes }),
initiallySelected: new fields.BooleanField({ initial: true }), initiallySelected: new fields.BooleanField({ initial: true }),
options: new fields.ArrayField(new fields.SchemaField({ options: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}), name: new fields.StringField({}),
value: new fields.StringField({}), value: new fields.StringField({})
}), { nullable: true, initial: null }), }),
{ nullable: true, initial: null }
),
dataField: new fields.StringField({}), dataField: new fields.StringField({}),
appliesOn: new fields.StringField({ choices: SYSTEM.EFFECTS.applyLocations }, { nullable: true, initial: null }), appliesOn: new fields.StringField(
applyLocationChoices: new MappingField(new fields.StringField({}), { nullable: true, initial: null }), { choices: SYSTEM.EFFECTS.applyLocations },
{ nullable: true, initial: null }
),
applyLocationChoices: new MappingField(new fields.StringField({}), {
nullable: true,
initial: null
}),
valueData: new fields.SchemaField({ valueData: new fields.SchemaField({
value: new fields.StringField({}), value: new fields.StringField({}),
fromValue: new fields.StringField({ initial: null, nullable: true }), fromValue: new fields.StringField({ initial: null, nullable: true }),
type: new fields.StringField({ initial: null, nullable: true }), type: new fields.StringField({ initial: null, nullable: true }),
hopeIncrease: new fields.StringField({ initial: null, nullable: true }) hopeIncrease: new fields.StringField({ initial: null, nullable: true })
}), })
})), })
actions: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartAction)), ),
}); actions: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartAction))
}
);
} }
get multiclassTier(){ get multiclassTier() {
return getTier(this.multiclass); return getTier(this.multiclass);
} }
async refresh(){ async refresh() {
if(this.refreshData){ if (this.refreshData) {
if(this.featureType.type === SYSTEM.ITEM.valueTypes.dice.id) { if (this.featureType.type === SYSTEM.ITEM.valueTypes.dice.id) {
const update = { "system.refreshData.refreshed": true }; const update = { 'system.refreshData.refreshed': true };
Object.keys(this.featureType.data.numbers).forEach(x => update[`system.featureType.data.numbers.-=${x}`] = null); Object.keys(this.featureType.data.numbers).forEach(
x => (update[`system.featureType.data.numbers.-=${x}`] = null)
);
await this.parent.update(update); await this.parent.update(update);
} } else {
else { await this.parent.update({ 'system.refreshData.refreshed': true });
await this.parent.update({ "system.refreshData.refreshed": true});
} }
} }
} }

View file

@ -1,7 +1,7 @@
export class MappingField extends foundry.data.fields.ObjectField { export class MappingField extends foundry.data.fields.ObjectField {
constructor(model, options) { constructor(model, options) {
if ( !(model instanceof foundry.data.fields.DataField) ) { if (!(model instanceof foundry.data.fields.DataField)) {
throw new Error("MappingField must have a DataField as its contained element"); throw new Error('MappingField must have a DataField as its contained element');
} }
super(options); super(options);
@ -27,7 +27,7 @@ export class MappingField extends foundry.data.fields.ObjectField {
/** @inheritdoc */ /** @inheritdoc */
_cleanType(value, options) { _cleanType(value, options) {
Object.entries(value).forEach(([k, v]) => value[k] = this.model.clean(v, options)); Object.entries(value).forEach(([k, v]) => (value[k] = this.model.clean(v, options)));
return value; return value;
} }
@ -37,9 +37,9 @@ export class MappingField extends foundry.data.fields.ObjectField {
getInitialValue(data) { getInitialValue(data) {
let keys = this.initialKeys; let keys = this.initialKeys;
const initial = super.getInitialValue(data); const initial = super.getInitialValue(data);
if ( !keys || !foundry.utils.isEmpty(initial) ) return initial; if (!keys || !foundry.utils.isEmpty(initial)) return initial;
if ( !(keys instanceof Array) ) keys = Object.keys(keys); if (!(keys instanceof Array)) keys = Object.keys(keys);
for ( const key of keys ) initial[key] = this._getInitialValueForKey(key); for (const key of keys) initial[key] = this._getInitialValueForKey(key);
return initial; return initial;
} }
@ -59,10 +59,10 @@ export class MappingField extends foundry.data.fields.ObjectField {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
_validateType(value, options={}) { _validateType(value, options = {}) {
if ( foundry.utils.getType(value) !== "Object" ) throw new Error("must be an Object"); if (foundry.utils.getType(value) !== 'Object') throw new Error('must be an Object');
const errors = this._validateValues(value, options); const errors = this._validateValues(value, options);
if ( !foundry.utils.isEmpty(errors) ) throw new foundry.data.fields.ModelValidationError(errors); if (!foundry.utils.isEmpty(errors)) throw new foundry.data.fields.ModelValidationError(errors);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -75,9 +75,9 @@ export class MappingField extends foundry.data.fields.ObjectField {
*/ */
_validateValues(value, options) { _validateValues(value, options) {
const errors = {}; const errors = {};
for ( const [k, v] of Object.entries(value) ) { for (const [k, v] of Object.entries(value)) {
const error = this.model.validate(v, options); const error = this.model.validate(v, options);
if ( error ) errors[k] = error; if (error) errors[k] = error;
} }
return errors; return errors;
} }
@ -85,12 +85,12 @@ export class MappingField extends foundry.data.fields.ObjectField {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
initialize(value, model, options={}) { initialize(value, model, options = {}) {
if ( !value ) return value; if (!value) return value;
const obj = {}; const obj = {};
const initialKeys = (this.initialKeys instanceof Array) ? this.initialKeys : Object.keys(this.initialKeys ?? {}); const initialKeys = this.initialKeys instanceof Array ? this.initialKeys : Object.keys(this.initialKeys ?? {});
const keys = this.initialKeysOnly ? initialKeys : Object.keys(value); const keys = this.initialKeysOnly ? initialKeys : Object.keys(value);
for ( const key of keys ) { for (const key of keys) {
const data = value[key] ?? this._getInitialValueForKey(key, value); const data = value[key] ?? this._getInitialValueForKey(key, value);
obj[key] = this.model.initialize(data, model, options); obj[key] = this.model.initialize(data, model, options);
} }
@ -101,9 +101,9 @@ export class MappingField extends foundry.data.fields.ObjectField {
/** @inheritdoc */ /** @inheritdoc */
_getField(path) { _getField(path) {
if ( path.length === 0 ) return this; if (path.length === 0) return this;
else if ( path.length === 1 ) return this.model; else if (path.length === 1) return this.model;
path.shift(); path.shift();
return this.model._getField(path); return this.model._getField(path);
} }
} }

View file

@ -1,30 +1,41 @@
import DaggerheartAction from "../action.mjs"; import DaggerheartAction from '../action.mjs';
import { MappingField } from "../fields.mjs"; import { MappingField } from '../fields.mjs';
export default class DhpEffects extends foundry.abstract.TypeDataModel { export default class DhpEffects extends foundry.abstract.TypeDataModel {
static defineSchema() { static defineSchema() {
const fields = foundry.data.fields; const fields = foundry.data.fields;
return { return {
effects: new MappingField(new fields.SchemaField({ effects: new MappingField(
new fields.SchemaField({
type: new fields.StringField({ choices: Object.keys(SYSTEM.EFFECTS.effectTypes) }), type: new fields.StringField({ choices: Object.keys(SYSTEM.EFFECTS.effectTypes) }),
valueType: new fields.StringField({ choices: Object.keys(SYSTEM.EFFECTS.valueTypes) }), valueType: new fields.StringField({ choices: Object.keys(SYSTEM.EFFECTS.valueTypes) }),
parseType: new fields.StringField({ choices: Object.keys(SYSTEM.EFFECTS.parseTypes) }), parseType: new fields.StringField({ choices: Object.keys(SYSTEM.EFFECTS.parseTypes) }),
initiallySelected: new fields.BooleanField({ initial: true }), initiallySelected: new fields.BooleanField({ initial: true }),
options: new fields.ArrayField(new fields.SchemaField({ options: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}), name: new fields.StringField({}),
value: new fields.StringField({}), value: new fields.StringField({})
}), { nullable: true, initial: null }), }),
{ nullable: true, initial: null }
),
dataField: new fields.StringField({}), dataField: new fields.StringField({}),
appliesOn: new fields.StringField({ choices: Object.keys(SYSTEM.EFFECTS.applyLocations) }, { nullable: true, initial: null }), appliesOn: new fields.StringField(
applyLocationChoices: new MappingField(new fields.StringField({}), { nullable: true, initial: null }), { choices: Object.keys(SYSTEM.EFFECTS.applyLocations) },
{ nullable: true, initial: null }
),
applyLocationChoices: new MappingField(new fields.StringField({}), {
nullable: true,
initial: null
}),
valueData: new fields.SchemaField({ valueData: new fields.SchemaField({
value: new fields.StringField({}), value: new fields.StringField({}),
fromValue: new fields.StringField({ initial: null, nullable: true }), fromValue: new fields.StringField({ initial: null, nullable: true }),
type: new fields.StringField({ initial: null, nullable: true }), type: new fields.StringField({ initial: null, nullable: true }),
hopeIncrease: new fields.StringField({ initial: null, nullable: true }) hopeIncrease: new fields.StringField({ initial: null, nullable: true })
}), })
})), })
actions: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartAction)), ),
actions: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartAction))
// actions: new fields.SchemaField({ // actions: new fields.SchemaField({
// damage: new fields.ArrayField(new fields.SchemaField({ // damage: new fields.ArrayField(new fields.SchemaField({
// type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.extendedDamageTypes), initial: SYSTEM.GENERAL.extendedDamageTypes.physical.id }), // type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.extendedDamageTypes), initial: SYSTEM.GENERAL.extendedDamageTypes.physical.id }),
@ -36,14 +47,14 @@ export default class DhpEffects extends foundry.abstract.TypeDataModel {
// refreshed: new fields.BooleanField({ initial: true }), // refreshed: new fields.BooleanField({ initial: true }),
// }), // }),
// }), // }),
} };
} }
get effectData(){ get effectData() {
const effectValues = Object.values(this.effects); const effectValues = Object.values(this.effects);
const effectCategories = Object.keys(SYSTEM.EFFECTS.effectTypes).reduce((acc, effectType) => { const effectCategories = Object.keys(SYSTEM.EFFECTS.effectTypes).reduce((acc, effectType) => {
acc[effectType] = effectValues.reduce((acc, effect) => { acc[effectType] = effectValues.reduce((acc, effect) => {
if(effect.type === effectType){ if (effect.type === effectType) {
acc.push({ ...effect, valueData: this.#parseValues(effect.parseType, effect.valueData) }); acc.push({ ...effect, valueData: this.#parseValues(effect.parseType, effect.valueData) });
} }
@ -56,7 +67,7 @@ export default class DhpEffects extends foundry.abstract.TypeDataModel {
return effectCategories; return effectCategories;
} }
#parseValues(parseType, values){ #parseValues(parseType, values) {
return Object.keys(values).reduce((acc, prop) => { return Object.keys(values).reduce((acc, prop) => {
acc[prop] = this.#parseValue(parseType, values[prop]); acc[prop] = this.#parseValue(parseType, values[prop]);
@ -65,7 +76,7 @@ export default class DhpEffects extends foundry.abstract.TypeDataModel {
} }
#parseValue(parseType, value) { #parseValue(parseType, value) {
switch(parseType){ switch (parseType) {
case SYSTEM.EFFECTS.parseTypes.number.id: case SYSTEM.EFFECTS.parseTypes.number.id:
return Number.parseInt(value); return Number.parseInt(value);
default: default:

View file

@ -1,10 +1,13 @@
const fields = foundry.data.fields; const fields = foundry.data.fields;
const featuresSchema = () => new fields.ArrayField(new fields.SchemaField({ const featuresSchema = () =>
new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}), name: new fields.StringField({}),
img: new fields.StringField({}), img: new fields.StringField({}),
uuid: new fields.StringField({}), uuid: new fields.StringField({}),
subclassLevel: new fields.StringField({}), subclassLevel: new fields.StringField({})
})) })
);
export default featuresSchema; export default featuresSchema;

View file

@ -4,6 +4,6 @@ export default class DhpMiscellaneous extends foundry.abstract.TypeDataModel {
return { return {
description: new fields.HTMLField({}), description: new fields.HTMLField({}),
quantity: new fields.NumberField({ initial: 1, integer: true }) quantity: new fields.NumberField({ initial: 1, integer: true })
} };
} }
} }

View file

@ -1,19 +1,20 @@
import { getPathValue, getTier } from "../helpers/utils.mjs"; import { getPathValue, getTier } from '../helpers/utils.mjs';
import { MappingField } from "./fields.mjs"; import { MappingField } from './fields.mjs';
const fields = foundry.data.fields; const fields = foundry.data.fields;
const attributeField = () => new fields.SchemaField({ const attributeField = () =>
new fields.SchemaField({
data: new fields.SchemaField({ data: new fields.SchemaField({
value: new fields.NumberField({ initial: 0, integer: true }), value: new fields.NumberField({ initial: 0, integer: true }),
base: new fields.NumberField({ initial: 0, integer: true }), base: new fields.NumberField({ initial: 0, integer: true }),
bonus: new fields.NumberField({ initial: 0, integer: true }), bonus: new fields.NumberField({ initial: 0, integer: true }),
actualValue: new fields.NumberField({ initial: 0, integer: true }), actualValue: new fields.NumberField({ initial: 0, integer: true }),
overrideValue: new fields.NumberField({ initial: 0, integer: true }), overrideValue: new fields.NumberField({ initial: 0, integer: true })
}), }),
levelMarks: new fields.ArrayField(new fields.NumberField({ nullable: true, initial: null, integer: true })), levelMarks: new fields.ArrayField(new fields.NumberField({ nullable: true, initial: null, integer: true })),
levelMark: new fields.NumberField({ nullable: true, initial: null, integer: true }), levelMark: new fields.NumberField({ nullable: true, initial: null, integer: true })
}); });
const levelUpTier = () => ({ const levelUpTier = () => ({
attributes: new MappingField(new fields.BooleanField()), attributes: new MappingField(new fields.BooleanField()),
@ -26,11 +27,13 @@ const levelUpTier = () => ({
severeDamageThreshold2: new MappingField(new fields.BooleanField()), severeDamageThreshold2: new MappingField(new fields.BooleanField()),
severeDamageThreshold3: new MappingField(new fields.BooleanField()), severeDamageThreshold3: new MappingField(new fields.BooleanField()),
severeDamageThreshold4: new MappingField(new fields.BooleanField()), severeDamageThreshold4: new MappingField(new fields.BooleanField()),
subclass: new MappingField(new fields.SchemaField({ subclass: new MappingField(
new fields.SchemaField({
multiclass: new fields.BooleanField(), multiclass: new fields.BooleanField(),
feature: new fields.StringField({}), feature: new fields.StringField({})
})), })
multiclass: new MappingField(new fields.BooleanField()), ),
multiclass: new MappingField(new fields.BooleanField())
}); });
// const weapon = () => new fields.SchemaField({ // const weapon = () => new fields.SchemaField({
@ -53,26 +56,28 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
health: new fields.SchemaField({ health: new fields.SchemaField({
value: new fields.NumberField({ initial: 0, integer: true }), value: new fields.NumberField({ initial: 0, integer: true }),
min: new fields.NumberField({ initial: 0, integer: true }), min: new fields.NumberField({ initial: 0, integer: true }),
max: new fields.NumberField({ initial: 6, integer: true }), max: new fields.NumberField({ initial: 6, integer: true })
}), }),
stress: new fields.SchemaField({ stress: new fields.SchemaField({
value: new fields.NumberField({ initial: 0, integer: true }), value: new fields.NumberField({ initial: 0, integer: true }),
min: new fields.NumberField({ initial: 0, integer: true }), min: new fields.NumberField({ initial: 0, integer: true }),
max: new fields.NumberField({ initial: 6, integer: true }), max: new fields.NumberField({ initial: 6, integer: true })
}), }),
hope: new fields.SchemaField({ hope: new fields.SchemaField({
value: new fields.NumberField({ initial: -1, integer: true }), // FIXME. Logic is gte and needs -1 in PC/Hope. Change to 0 value: new fields.NumberField({ initial: -1, integer: true }), // FIXME. Logic is gte and needs -1 in PC/Hope. Change to 0
min: new fields.NumberField({ initial: 0, integer: true }), min: new fields.NumberField({ initial: 0, integer: true })
}), })
}), }),
bonuses: new fields.SchemaField({ bonuses: new fields.SchemaField({
damage: new fields.ArrayField(new fields.SchemaField({ damage: new fields.ArrayField(
new fields.SchemaField({
value: new fields.NumberField({ integer: true, initial: 0 }), value: new fields.NumberField({ integer: true, initial: 0 }),
type: new fields.StringField({ nullable: true }), type: new fields.StringField({ nullable: true }),
initiallySelected: new fields.BooleanField(), initiallySelected: new fields.BooleanField(),
hopeIncrease: new fields.StringField({ initial: null, nullable: true }), hopeIncrease: new fields.StringField({ initial: null, nullable: true }),
description: new fields.StringField({}), description: new fields.StringField({})
})), })
)
}), }),
attributes: new fields.SchemaField({ attributes: new fields.SchemaField({
agility: attributeField(), agility: attributeField(),
@ -80,145 +85,178 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
finesse: attributeField(), finesse: attributeField(),
instinct: attributeField(), instinct: attributeField(),
presence: attributeField(), presence: attributeField(),
knowledge: attributeField(), knowledge: attributeField()
}), }),
proficiency: new fields.SchemaField({ proficiency: new fields.SchemaField({
value: new fields.NumberField({ initial: 1, integer: true}), value: new fields.NumberField({ initial: 1, integer: true }),
min: new fields.NumberField({ initial: 1, integer: true}), min: new fields.NumberField({ initial: 1, integer: true }),
max: new fields.NumberField({ initial: 6, integer: true}), max: new fields.NumberField({ initial: 6, integer: true })
}), }),
damageThresholds: new fields.SchemaField({ damageThresholds: new fields.SchemaField({
minor: new fields.NumberField({ initial: 0, integer: true }), minor: new fields.NumberField({ initial: 0, integer: true }),
major: new fields.NumberField({ initial: 0, integer: true }), major: new fields.NumberField({ initial: 0, integer: true }),
severe: new fields.NumberField({ initial: 0, integer: true }), severe: new fields.NumberField({ initial: 0, integer: true })
}), }),
evasion: new fields.NumberField({ initial: 0, integer: true }), evasion: new fields.NumberField({ initial: 0, integer: true }),
// armor: new fields.SchemaField({ // armor: new fields.SchemaField({
// value: new fields.NumberField({ initial: 0, integer: true }), // value: new fields.NumberField({ initial: 0, integer: true }),
// customValue: new fields.NumberField({ initial: null, nullable: true }), // customValue: new fields.NumberField({ initial: null, nullable: true }),
// }), // }),
experiences: new fields.ArrayField(new fields.SchemaField({ experiences: new fields.ArrayField(
new fields.SchemaField({
id: new fields.StringField({ required: true }), id: new fields.StringField({ required: true }),
level: new fields.NumberField({ required: true, integer: true }), level: new fields.NumberField({ required: true, integer: true }),
description: new fields.StringField({}), description: new fields.StringField({}),
value: new fields.NumberField({ integer: true, nullable: true, initial: null }), value: new fields.NumberField({ integer: true, nullable: true, initial: null })
}), { }),
{
initial: [ initial: [
{ id: foundry.utils.randomID(), level: 1, description: '', value: 2 }, { id: foundry.utils.randomID(), level: 1, description: '', value: 2 },
{ id: foundry.utils.randomID(), level: 1, description: '', value: 2 }, { id: foundry.utils.randomID(), level: 1, description: '', value: 2 }
] ]
}), }
),
gold: new fields.SchemaField({ gold: new fields.SchemaField({
coins: new fields.NumberField({ initial: 0, integer: true }), coins: new fields.NumberField({ initial: 0, integer: true }),
handfulls: new fields.NumberField({ initial: 0, integer: true }), handfulls: new fields.NumberField({ initial: 0, integer: true }),
bags: new fields.NumberField({ initial: 0, integer: true }), bags: new fields.NumberField({ initial: 0, integer: true }),
chests: new fields.NumberField({ initial: 0, integer: true }), chests: new fields.NumberField({ initial: 0, integer: true })
}), }),
pronouns: new fields.StringField({}), pronouns: new fields.StringField({}),
domainData: new fields.SchemaField({ domainData: new fields.SchemaField({
maxLoadout: new fields.NumberField({ initial: 2, integer: true }), maxLoadout: new fields.NumberField({ initial: 2, integer: true }),
maxCards: new fields.NumberField({ initial: 2, integer: true }), maxCards: new fields.NumberField({ initial: 2, integer: true })
}), }),
levelData: new fields.SchemaField({ levelData: new fields.SchemaField({
currentLevel: new fields.NumberField({ initial: 1, integer: true }), currentLevel: new fields.NumberField({ initial: 1, integer: true }),
changedLevel: new fields.NumberField({ initial: 1, integer: true }), changedLevel: new fields.NumberField({ initial: 1, integer: true }),
levelups: new MappingField(new fields.SchemaField({ levelups: new MappingField(
new fields.SchemaField({
level: new fields.NumberField({ required: true, integer: true }), level: new fields.NumberField({ required: true, integer: true }),
tier1: new fields.SchemaField({ tier1: new fields.SchemaField({
...levelUpTier() ...levelUpTier()
}), }),
tier2: new fields.SchemaField({ tier2: new fields.SchemaField(
{
...levelUpTier() ...levelUpTier()
}, { nullable: true, initial: null }), },
tier3: new fields.SchemaField({ { nullable: true, initial: null }
),
tier3: new fields.SchemaField(
{
...levelUpTier() ...levelUpTier()
}, { nullable: true, initial: null }), },
})), { nullable: true, initial: null }
)
})
)
}), }),
story: new fields.SchemaField({ story: new fields.SchemaField({
background: new fields.HTMLField(), background: new fields.HTMLField(),
appearance: new fields.HTMLField(), appearance: new fields.HTMLField(),
connections: new fields.HTMLField(), connections: new fields.HTMLField(),
scars: new fields.ArrayField(new fields.SchemaField({ scars: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}), name: new fields.StringField({}),
description: new fields.HTMLField(), description: new fields.HTMLField()
})), })
)
}), }),
description: new fields.StringField({}), description: new fields.StringField({}),
//Temporary until new FoundryVersion fix --> See Armor.Mjs DataPreparation //Temporary until new FoundryVersion fix --> See Armor.Mjs DataPreparation
armorMarks: new fields.SchemaField({ armorMarks: new fields.SchemaField({
max: new fields.NumberField({ initial: 6, integer: true }), max: new fields.NumberField({ initial: 6, integer: true }),
value: new fields.NumberField({ initial: 0, integer: true }), value: new fields.NumberField({ initial: 0, integer: true })
}), })
} };
} }
get canLevelUp(){ get canLevelUp() {
// return Object.values(this.levels.data).some(x => !x.completed); // return Object.values(this.levels.data).some(x => !x.completed);
return this.levelData.currentLevel !== this.levelData.changedLevel; return this.levelData.currentLevel !== this.levelData.changedLevel;
} }
get tier(){ get tier() {
return this.#getTier(this.levelData.currentLevel); return this.#getTier(this.levelData.currentLevel);
} }
get ancestry(){ get ancestry() {
return this.parent.items.find(x => x.type === 'ancestry') ?? null; return this.parent.items.find(x => x.type === 'ancestry') ?? null;
} }
get class(){ get class() {
return this.parent.items.find(x => x.type === 'class' && !x.system.multiclass) ?? null; return this.parent.items.find(x => x.type === 'class' && !x.system.multiclass) ?? null;
} }
get multiclass(){ get multiclass() {
return this.parent.items.find(x => x.type === 'class' && x.system.multiclass) ?? null; return this.parent.items.find(x => x.type === 'class' && x.system.multiclass) ?? null;
} }
get multiclassSubclass(){ get multiclassSubclass() {
return this.parent.items.find(x => x.type === 'subclass' && x.system.multiclass) ?? null; return this.parent.items.find(x => x.type === 'subclass' && x.system.multiclass) ?? null;
} }
get subclass(){ get subclass() {
return this.parent.items.find(x => x.type === 'subclass' && !x.system.multiclass) ?? null; return this.parent.items.find(x => x.type === 'subclass' && !x.system.multiclass) ?? null;
} }
get subclassFeatures(){ get subclassFeatures() {
const subclass = this.subclass; const subclass = this.subclass;
const multiclass = this.multiclassSubclass; const multiclass = this.multiclassSubclass;
const subclassItems = this.parent.items.filter(x => x.type === 'feature' && x.system.type === 'subclass'); const subclassItems = this.parent.items.filter(x => x.type === 'feature' && x.system.type === 'subclass');
return { return {
subclass: !subclass ? {} : { subclass: !subclass
foundation: subclassItems.filter(x => subclass.system.foundationFeature.abilities.some(ability => ability.uuid === x.uuid)), ? {}
specialization: subclassItems.filter(x => subclass.system.specializationFeature.abilities.some(ability => ability.uuid === x.uuid)), : {
mastery: subclassItems.filter(x => subclass.system.masteryFeature.abilities.some(ability => ability.uuid === x.uuid)), foundation: subclassItems.filter(x =>
subclass.system.foundationFeature.abilities.some(ability => ability.uuid === x.uuid)
),
specialization: subclassItems.filter(x =>
subclass.system.specializationFeature.abilities.some(ability => ability.uuid === x.uuid)
),
mastery: subclassItems.filter(x =>
subclass.system.masteryFeature.abilities.some(ability => ability.uuid === x.uuid)
)
}, },
multiclassSubclass: !multiclass ? {} : { multiclassSubclass: !multiclass
foundation: subclassItems.filter(x => multiclass.system.foundationFeature.abilities.some(ability => ability.uuid === x.uuid)), ? {}
specialization: subclassItems.filter(x => multiclass.system.specializationFeature.abilities.some(ability => ability.uuid === x.uuid)), : {
mastery: subclassItems.filter(x => multiclass.system.masteryFeature.abilities.some(ability => ability.uuid === x.uuid)), foundation: subclassItems.filter(x =>
} multiclass.system.foundationFeature.abilities.some(ability => ability.uuid === x.uuid)
),
specialization: subclassItems.filter(x =>
multiclass.system.specializationFeature.abilities.some(ability => ability.uuid === x.uuid)
),
mastery: subclassItems.filter(x =>
multiclass.system.masteryFeature.abilities.some(ability => ability.uuid === x.uuid)
)
} }
};
} }
get community(){ get community() {
return this.parent.items.find(x => x.type === 'community') ?? null; return this.parent.items.find(x => x.type === 'community') ?? null;
} }
get classFeatures(){ get classFeatures() {
return this.parent.items.filter(x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.class.id && !x.system.multiclass); return this.parent.items.filter(
x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.class.id && !x.system.multiclass
);
} }
get multiclassFeatures(){ get multiclassFeatures() {
return this.parent.items.filter(x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.class.id && x.system.multiclass); return this.parent.items.filter(
x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.class.id && x.system.multiclass
);
} }
get domains(){ get domains() {
const classDomains = this.class ? this.class.system.domains : []; const classDomains = this.class ? this.class.system.domains : [];
const multiclassDomains = this.multiclass ? this.multiclass.system.domains : []; const multiclassDomains = this.multiclass ? this.multiclass.system.domains : [];
return [...classDomains, ...multiclassDomains] return [...classDomains, ...multiclassDomains];
} }
get domainCards(){ get domainCards() {
const domainCards = this.parent.items.filter(x => x.type === 'domainCard'); const domainCards = this.parent.items.filter(x => x.type === 'domainCard');
const loadout = domainCards.filter(x => !x.system.inVault); const loadout = domainCards.filter(x => !x.system.inVault);
const vault = domainCards.filter(x => x.system.inVault); const vault = domainCards.filter(x => x.system.inVault);
@ -230,13 +268,17 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
}; };
} }
get armor(){ get armor() {
return this.parent.items.find(x => x.type === 'armor'); return this.parent.items.find(x => x.type === 'armor');
} }
get activeWeapons(){ get activeWeapons() {
const primaryWeapon = this.parent.items.find(x => x.type === 'weapon' && x.system.active && !x.system.secondary); const primaryWeapon = this.parent.items.find(
const secondaryWeapon = this.parent.items.find(x => x.type === 'weapon' && x.system.active && x.system.secondary); x => x.type === 'weapon' && x.system.active && !x.system.secondary
);
const secondaryWeapon = this.parent.items.find(
x => x.type === 'weapon' && x.system.active && x.system.secondary
);
return { return {
primary: this.#weaponData(primaryWeapon), primary: this.#weaponData(primaryWeapon),
secondary: this.#weaponData(secondaryWeapon), secondary: this.#weaponData(secondaryWeapon),
@ -244,16 +286,18 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
}; };
} }
get inventoryWeapons(){ get inventoryWeapons() {
const inventoryWeaponFirst = this.parent.items.find(x => x.type === 'weapon' && x.system.inventoryWeapon === 1); const inventoryWeaponFirst = this.parent.items.find(x => x.type === 'weapon' && x.system.inventoryWeapon === 1);
const inventoryWeaponSecond = this.parent.items.find(x => x.type === 'weapon' && x.system.inventoryWeapon === 2); const inventoryWeaponSecond = this.parent.items.find(
x => x.type === 'weapon' && x.system.inventoryWeapon === 2
);
return { return {
first: this.#weaponData(inventoryWeaponFirst), first: this.#weaponData(inventoryWeaponFirst),
second: this.#weaponData(inventoryWeaponSecond), second: this.#weaponData(inventoryWeaponSecond)
}; };
} }
get totalAttributeMarks(){ get totalAttributeMarks() {
return Object.keys(this.levelData.levelups).reduce((nr, level) => { return Object.keys(this.levelData.levelups).reduce((nr, level) => {
const nrAttributeMarks = Object.keys(this.levelData.levelups[level]).reduce((nr, tier) => { const nrAttributeMarks = Object.keys(this.levelData.levelups[level]).reduce((nr, tier) => {
nr += Object.keys(this.levelData.levelups[level][tier]?.attributes ?? {}).length * 2; nr += Object.keys(this.levelData.levelups[level][tier]?.attributes ?? {}).length * 2;
@ -267,10 +311,10 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
}, []); }, []);
} }
get availableAttributeMarks(){ get availableAttributeMarks() {
const attributeMarks = Object.keys(this.attributes).flatMap(y => this.attributes[y].levelMarks); const attributeMarks = Object.keys(this.attributes).flatMap(y => this.attributes[y].levelMarks);
return this.totalAttributeMarks.reduce((acc, attribute) => { return this.totalAttributeMarks.reduce((acc, attribute) => {
if(!attributeMarks.findSplice(x => x === attribute)){ if (!attributeMarks.findSplice(x => x === attribute)) {
acc.push(attribute); acc.push(attribute);
} }
@ -278,14 +322,14 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
}, []); }, []);
} }
get effects(){ get effects() {
return this.parent.items.reduce((acc, item) => { return this.parent.items.reduce((acc, item) => {
const effects = item.system.effectData; const effects = item.system.effectData;
if(effects && !item.system.disabled){ if (effects && !item.system.disabled) {
for(var key in effects){ for (var key in effects) {
const effect = effects[key]; const effect = effects[key];
for(var effectEntry of effect){ for (var effectEntry of effect) {
if(!acc[key]) acc[key] = []; if (!acc[key]) acc[key] = [];
acc[key].push({ name: item.name, value: effectEntry }); acc[key].push({ name: item.name, value: effectEntry });
} }
} }
@ -295,45 +339,52 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
}, {}); }, {});
} }
get refreshableFeatures(){ get refreshableFeatures() {
return this.parent.items.reduce((acc, x) => { return this.parent.items.reduce(
if(x.type === 'feature' && x.system.refreshData.type){ (acc, x) => {
if (x.type === 'feature' && x.system.refreshData.type) {
acc[x.system.refreshData.type].push(x); acc[x.system.refreshData.type].push(x);
} }
return acc; return acc;
}, { shortRest: [], longRest: [] }); },
{ shortRest: [], longRest: [] }
);
} }
#weaponData(weapon){ #weaponData(weapon) {
return weapon ? { return weapon
? {
name: weapon.name, name: weapon.name,
trait: CONFIG.daggerheart.ACTOR.abilities[weapon.system.trait].name, //Should not be done in data? trait: CONFIG.daggerheart.ACTOR.abilities[weapon.system.trait].name, //Should not be done in data?
range: CONFIG.daggerheart.GENERAL.range[weapon.system.range], range: CONFIG.daggerheart.GENERAL.range[weapon.system.range],
damage: { damage: {
value: weapon.system.damage.value, value: weapon.system.damage.value,
type: CONFIG.daggerheart.GENERAL.damageTypes[weapon.system.damage.type], type: CONFIG.daggerheart.GENERAL.damageTypes[weapon.system.damage.type]
}, },
feature: CONFIG.daggerheart.ITEM.weaponFeatures[weapon.system.feature], feature: CONFIG.daggerheart.ITEM.weaponFeatures[weapon.system.feature],
img: weapon.img, img: weapon.img,
uuid: weapon.uuid uuid: weapon.uuid
} : null }
: null;
} }
prepareDerivedData(){ prepareDerivedData() {
this.resources.hope.max = 6 - this.story.scars.length; this.resources.hope.max = 6 - this.story.scars.length;
if(this.resources.hope.value >= this.resources.hope.max){ if (this.resources.hope.value >= this.resources.hope.max) {
this.resources.hope.value = Math.max(this.resources.hope.max-1, 0); this.resources.hope.value = Math.max(this.resources.hope.max - 1, 0);
} }
for(var attributeKey in this.attributes){ for (var attributeKey in this.attributes) {
const attribute = this.attributes[attributeKey]; const attribute = this.attributes[attributeKey];
attribute.levelMark = attribute.levelMarks.find(x => this.isSameTier(x)) ?? null; attribute.levelMark = attribute.levelMarks.find(x => this.isSameTier(x)) ?? null;
const actualValue = attribute.data.base + attribute.levelMarks.length + attribute.data.bonus; const actualValue = attribute.data.base + attribute.levelMarks.length + attribute.data.bonus;
attribute.data.actualValue = actualValue; attribute.data.actualValue = actualValue;
attribute.data.value = attribute.data.overrideValue ? attribute.data.overrideValue : attribute.data.actualValue; attribute.data.value = attribute.data.overrideValue
? attribute.data.overrideValue
: attribute.data.actualValue;
} }
this.evasion = this.class?.system?.evasion ?? 0; this.evasion = this.class?.system?.evasion ?? 0;
@ -344,30 +395,50 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
this.applyEffects(); this.applyEffects();
} }
applyLevels(){ applyLevels() {
let healthBonus = 0, stressBonus = 0, proficiencyBonus = 0, evasionBonus = 0, armorBonus = 0, minorThresholdBonus = 0, majorThresholdBonus = 0, severeThresholdBonus = 0; let healthBonus = 0,
stressBonus = 0,
proficiencyBonus = 0,
evasionBonus = 0,
armorBonus = 0,
minorThresholdBonus = 0,
majorThresholdBonus = 0,
severeThresholdBonus = 0;
let experienceBonuses = {}; let experienceBonuses = {};
let advancementFirst = null, advancementSecond = null; let advancementFirst = null,
for(var level in this.levelData.levelups){ advancementSecond = null;
for (var level in this.levelData.levelups) {
var levelData = this.levelData.levelups[level]; var levelData = this.levelData.levelups[level];
for(var tier in levelData){ for (var tier in levelData) {
var tierData = levelData[tier]; var tierData = levelData[tier];
if(tierData){ if (tierData) {
healthBonus += Object.keys(tierData.hitPointSlots).length; healthBonus += Object.keys(tierData.hitPointSlots).length;
stressBonus += Object.keys(tierData.stressSlots).length; stressBonus += Object.keys(tierData.stressSlots).length;
proficiencyBonus += Object.keys(tierData.proficiency).length; proficiencyBonus += Object.keys(tierData.proficiency).length;
advancementFirst = Object.keys(tierData.subclass).length > 0 && (level >= 5 && level <= 7) ? { ...tierData.subclass[0], tier: getTier(Number.parseInt(level), true) } : advancementFirst; advancementFirst =
advancementSecond = Object.keys(tierData.subclass).length > 0 && (level >= 8 && level <= 10) ? { ...tierData.subclass[0], tier: getTier(Number.parseInt(level), true) } : advancementSecond; Object.keys(tierData.subclass).length > 0 && level >= 5 && level <= 7
? { ...tierData.subclass[0], tier: getTier(Number.parseInt(level), true) }
: advancementFirst;
advancementSecond =
Object.keys(tierData.subclass).length > 0 && level >= 8 && level <= 10
? { ...tierData.subclass[0], tier: getTier(Number.parseInt(level), true) }
: advancementSecond;
for(var index in Object.keys(tierData.experiences)){ for (var index in Object.keys(tierData.experiences)) {
for(var experienceKey in tierData.experiences[index]){ for (var experienceKey in tierData.experiences[index]) {
var experience = tierData.experiences[index][experienceKey]; var experience = tierData.experiences[index][experienceKey];
experienceBonuses[experience] = experienceBonuses[experience] ? experienceBonuses[experience]+1 : 1; experienceBonuses[experience] = experienceBonuses[experience]
? experienceBonuses[experience] + 1
: 1;
} }
} }
evasionBonus += Object.keys(tierData.armorOrEvasionSlot).filter(x => tierData.armorOrEvasionSlot[x] === 'evasion').length; evasionBonus += Object.keys(tierData.armorOrEvasionSlot).filter(
armorBonus += Object.keys(tierData.armorOrEvasionSlot).filter(x => tierData.armorOrEvasionSlot[x] === 'armor').length; x => tierData.armorOrEvasionSlot[x] === 'evasion'
).length;
armorBonus += Object.keys(tierData.armorOrEvasionSlot).filter(
x => tierData.armorOrEvasionSlot[x] === 'armor'
).length;
majorThresholdBonus += Object.keys(tierData.majorDamageThreshold2).length * 2; majorThresholdBonus += Object.keys(tierData.majorDamageThreshold2).length * 2;
severeThresholdBonus += Object.keys(tierData.severeDamageThreshold2).length * 2; severeThresholdBonus += Object.keys(tierData.severeDamageThreshold2).length * 2;
@ -383,7 +454,7 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
this.evasion += evasionBonus; this.evasion += evasionBonus;
this.armorMarks = { this.armorMarks = {
max: this.armor ? this.armor.system.marks.max + armorBonus : 0, max: this.armor ? this.armor.system.marks.max + armorBonus : 0,
value: this.armor ? this.armor.system.marks.value : 0, value: this.armor ? this.armor.system.marks.value : 0
}; };
this.damageThresholds.minor += minorThresholdBonus; this.damageThresholds.minor += minorThresholdBonus;
this.damageThresholds.major += majorThresholdBonus; this.damageThresholds.major += majorThresholdBonus;
@ -392,39 +463,40 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
this.experiences = this.experiences.map(x => ({ ...x, value: x.value + (experienceBonuses[x.id] ?? 0) })); this.experiences = this.experiences.map(x => ({ ...x, value: x.value + (experienceBonuses[x.id] ?? 0) }));
const subclassFeatures = this.subclassFeatures; const subclassFeatures = this.subclassFeatures;
if(advancementFirst){ if (advancementFirst) {
if(advancementFirst.multiclass){ if (advancementFirst.multiclass) {
this.multiclassSubclass.system[`${advancementFirst.feature}Feature`].unlocked = true; this.multiclassSubclass.system[`${advancementFirst.feature}Feature`].unlocked = true;
this.multiclassSubclass.system[`${advancementFirst.feature}Feature`].tier = advancementFirst.tier; this.multiclassSubclass.system[`${advancementFirst.feature}Feature`].tier = advancementFirst.tier;
subclassFeatures.multiclassSubclass[advancementFirst.feature].forEach(x => x.system.disabled = false); subclassFeatures.multiclassSubclass[advancementFirst.feature].forEach(x => (x.system.disabled = false));
} else { } else {
this.subclass.system[`${advancementFirst.feature}Feature`].unlocked = true; this.subclass.system[`${advancementFirst.feature}Feature`].unlocked = true;
this.subclass.system[`${advancementFirst.feature}Feature`].tier = advancementFirst.tier; this.subclass.system[`${advancementFirst.feature}Feature`].tier = advancementFirst.tier;
subclassFeatures.subclass[advancementFirst.feature].forEach(x => x.system.disabled = false); subclassFeatures.subclass[advancementFirst.feature].forEach(x => (x.system.disabled = false));
} }
} }
if(advancementSecond){ if (advancementSecond) {
if(advancementSecond.multiclass){ if (advancementSecond.multiclass) {
this.multiclassSubclass.system[`${advancementSecond.feature}Feature`].unlocked = true; this.multiclassSubclass.system[`${advancementSecond.feature}Feature`].unlocked = true;
this.multiclassSubclass.system[`${advancementSecond.feature}Feature`].tier = advancementSecond.tier; this.multiclassSubclass.system[`${advancementSecond.feature}Feature`].tier = advancementSecond.tier;
subclassFeatures.multiclassSubclass[advancementSecond.feature].forEach(x => x.system.disabled = false); subclassFeatures.multiclassSubclass[advancementSecond.feature].forEach(
x => (x.system.disabled = false)
);
} else { } else {
this.subclass.system[`${advancementSecond.feature}Feature`].unlocked = true; this.subclass.system[`${advancementSecond.feature}Feature`].unlocked = true;
this.subclass.system[`${advancementSecond.feature}Feature`].tier = advancementSecond.tier; this.subclass.system[`${advancementSecond.feature}Feature`].tier = advancementSecond.tier;
subclassFeatures.subclass[advancementSecond.feature].forEach(x => x.system.disabled = false); subclassFeatures.subclass[advancementSecond.feature].forEach(x => (x.system.disabled = false));
} }
} }
//General progression //General progression
for(var i = 0; i < this.levelData.currentLevel; i++){ for (var i = 0; i < this.levelData.currentLevel; i++) {
const tier = getTier(i+1); const tier = getTier(i + 1);
if(tier !== 'tier0'){ if (tier !== 'tier0') {
this.domainData.maxLoadout = Math.min(this.domainData.maxLoadout+1, 5); this.domainData.maxLoadout = Math.min(this.domainData.maxLoadout + 1, 5);
this.domainData.maxCards += 1; this.domainData.maxCards += 1;
} }
switch(tier){ switch (tier) {
case 'tier1': case 'tier1':
this.damageThresholds.severe += 2; this.damageThresholds.severe += 2;
break; break;
@ -440,12 +512,12 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
} }
} }
applyEffects(){ applyEffects() {
const effects = this.effects; const effects = this.effects;
for(var key in effects){ for (var key in effects) {
const effectType = effects[key]; const effectType = effects[key];
for(var effect of effectType) { for (var effect of effectType) {
switch(key) { switch (key) {
case SYSTEM.EFFECTS.effectTypes.health.id: case SYSTEM.EFFECTS.effectTypes.health.id:
this.resources.health.max += effect.value.valueData.value; this.resources.health.max += effect.value.valueData.value;
break; break;
@ -459,39 +531,32 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
description: effect.name, description: effect.name,
hopeIncrease: effect.value.valueData.hopeIncrease, hopeIncrease: effect.value.valueData.hopeIncrease,
initiallySelected: effect.value.initiallySelected, initiallySelected: effect.value.initiallySelected,
appliesOn: effect.value.appliesOn, appliesOn: effect.value.appliesOn
}); });
} }
} }
} }
} }
getBurden(primary, secondary){ getBurden(primary, secondary) {
const twoHanded = const twoHanded =
primary?.system?.burden === 'twoHanded' || primary?.system?.burden === 'twoHanded' ||
secondary?.system?.burden === 'twoHanded' || secondary?.system?.burden === 'twoHanded' ||
( (primary?.system?.burden === 'oneHanded' && secondary?.system?.burden === 'oneHanded');
primary?.system?.burden === 'oneHanded' &&
secondary?.system?.burden === 'oneHanded'
);
const oneHanded = const oneHanded =
!twoHanded && !twoHanded && (primary?.system?.burden === 'oneHanded' || secondary?.system?.burden === 'oneHanded');
(
primary?.system?.burden === 'oneHanded' ||
secondary?.system?.burden === 'oneHanded'
);
return twoHanded ? 'twoHanded' : oneHanded ? 'oneHanded' : null; return twoHanded ? 'twoHanded' : oneHanded ? 'oneHanded' : null;
} }
isSameTier(level){ isSameTier(level) {
return this.#getTier(this.levelData.currentLevel) === this.#getTier(level); return this.#getTier(this.levelData.currentLevel) === this.#getTier(level);
} }
#getTier(level){ #getTier(level) {
if(level >= 8) return 3; if (level >= 8) return 3;
else if(level >= 5) return 2; else if (level >= 5) return 2;
else if(level >= 2) return 1; else if (level >= 2) return 1;
else return 0; else return 0;
} }
} }

View file

@ -1,5 +1,5 @@
import { getTier } from "../helpers/utils.mjs"; import { getTier } from '../helpers/utils.mjs';
import featuresSchema from "./interface/featuresSchema.mjs"; import featuresSchema from './interface/featuresSchema.mjs';
import DaggerheartFeature from './feature.mjs'; import DaggerheartFeature from './feature.mjs';
export default class DhpSubclass extends foundry.abstract.TypeDataModel { export default class DhpSubclass extends foundry.abstract.TypeDataModel {
@ -7,28 +7,33 @@ export default class DhpSubclass extends foundry.abstract.TypeDataModel {
const fields = foundry.data.fields; const fields = foundry.data.fields;
return { return {
description: new fields.HTMLField({}), description: new fields.HTMLField({}),
spellcastingTrait: new fields.StringField({ choices: SYSTEM.ACTOR.abilities, integer: false, nullable: true, initial: null }), spellcastingTrait: new fields.StringField({
choices: SYSTEM.ACTOR.abilities,
integer: false,
nullable: true,
initial: null
}),
foundationFeature: new fields.SchemaField({ foundationFeature: new fields.SchemaField({
description: new fields.HTMLField({}), description: new fields.HTMLField({}),
abilities: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartFeature)), abilities: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartFeature))
}), }),
specializationFeature: new fields.SchemaField({ specializationFeature: new fields.SchemaField({
unlocked: new fields.BooleanField({ initial: false }), unlocked: new fields.BooleanField({ initial: false }),
tier: new fields.NumberField({ initial: null, nullable: true, integer: true }), tier: new fields.NumberField({ initial: null, nullable: true, integer: true }),
description: new fields.HTMLField({}), description: new fields.HTMLField({}),
abilities: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartFeature)), abilities: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartFeature))
}), }),
masteryFeature: new fields.SchemaField({ masteryFeature: new fields.SchemaField({
unlocked: new fields.BooleanField({ initial: false }), unlocked: new fields.BooleanField({ initial: false }),
tier: new fields.NumberField({ initial: null, nullable: true, integer: true }), tier: new fields.NumberField({ initial: null, nullable: true, integer: true }),
description: new fields.HTMLField({}), description: new fields.HTMLField({}),
abilities: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartFeature)), abilities: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartFeature))
}), }),
multiclass: new fields.NumberField({ initial: null, nullable: true, integer: true }), multiclass: new fields.NumberField({ initial: null, nullable: true, integer: true })
} };
} }
get multiclassTier(){ get multiclassTier() {
return getTier(this.multiclass); return getTier(this.multiclass);
} }
} }

View file

@ -9,29 +9,32 @@ export default class DhpWeapon extends foundry.abstract.TypeDataModel {
range: new fields.StringField({ choices: SYSTEM.GENERAL.range, integer: false }), range: new fields.StringField({ choices: SYSTEM.GENERAL.range, integer: false }),
damage: new fields.SchemaField({ damage: new fields.SchemaField({
value: new fields.StringField({}), value: new fields.StringField({}),
type: new fields.StringField({ choices: SYSTEM.GENERAL.damageTypes, integer: false }), type: new fields.StringField({ choices: SYSTEM.GENERAL.damageTypes, integer: false })
}), }),
burden: new fields.StringField({ choices: SYSTEM.GENERAL.burden, integer: false }), burden: new fields.StringField({ choices: SYSTEM.GENERAL.burden, integer: false }),
feature: new fields.StringField({ choices: SYSTEM.ITEM.weaponFeatures, integer: false, blank:true }), feature: new fields.StringField({ choices: SYSTEM.ITEM.weaponFeatures, integer: false, blank: true }),
quantity: new fields.NumberField({ initial: 1, integer: true }), quantity: new fields.NumberField({ initial: 1, integer: true }),
description: new fields.HTMLField({}), description: new fields.HTMLField({})
} };
} }
prepareDerivedData(){ prepareDerivedData() {
if(this.parent.parent){ if (this.parent.parent) {
this.applyEffects(); this.applyEffects();
} }
} }
applyEffects(){ applyEffects() {
const effects = this.parent.parent.system.effects; const effects = this.parent.parent.system.effects;
for(var key in effects){ for (var key in effects) {
const effectType = effects[key]; const effectType = effects[key];
for(var effect of effectType) { for (var effect of effectType) {
switch(key) { switch (key) {
case SYSTEM.EFFECTS.effectTypes.reach.id: case SYSTEM.EFFECTS.effectTypes.reach.id:
if(SYSTEM.GENERAL.range[this.range].distance < SYSTEM.GENERAL.range[effect.valueData.value].distance){ if (
SYSTEM.GENERAL.range[this.range].distance <
SYSTEM.GENERAL.range[effect.valueData.value].distance
) {
this.range = effect.valueData.value; this.range = effect.valueData.value;
} }

View file

@ -5,22 +5,22 @@ export default class SelectDialog extends Dialog {
this.data = { this.data = {
title: data.title, title: data.title,
buttons: data.buttons, buttons: data.buttons,
content: renderTemplate("systems/daggerheart/templates/dialog/item-select.hbs", { content: renderTemplate('systems/daggerheart/templates/dialog/item-select.hbs', {
items: data.choices items: data.choices
}), })
}; };
this.actor = data.actor; this.actor = data.actor;
this.actionCostMax = data.actionCostMax; this.actionCostMax = data.actionCostMax;
this.nrChoices = data.nrChoices; this.nrChoices = data.nrChoices;
this.validate= data.validate; this.validate = data.validate;
} }
async getData(options={}) { async getData(options = {}) {
let buttons = Object.keys(this.data.buttons).reduce((obj, key) => { let buttons = Object.keys(this.data.buttons).reduce((obj, key) => {
let b = this.data.buttons[key]; let b = this.data.buttons[key];
b.cssClass = (this.data.default === key ? [key, "default", "bright"] : [key]).join(" "); b.cssClass = (this.data.default === key ? [key, 'default', 'bright'] : [key]).join(' ');
if ( b.condition !== false ) obj[key] = b; if (b.condition !== false) obj[key] = b;
return obj; return obj;
}, {}); }, {});
@ -37,9 +37,9 @@ export default class SelectDialog extends Dialog {
$(html).find('.item-button').click(this.selectChoice); $(html).find('.item-button').click(this.selectChoice);
} }
selectChoice = async (event) => { selectChoice = async event => {
if(this.validate){ if (this.validate) {
if(!this.validate(event.currentTarget.dataset.validateProp)){ if (!this.validate(event.currentTarget.dataset.validateProp)) {
return; return;
} }
} }
@ -48,12 +48,12 @@ export default class SelectDialog extends Dialog {
$(event.currentTarget).find('i')[0].classList.toggle('checked'); $(event.currentTarget).find('i')[0].classList.toggle('checked');
const buttons = $(this.element[0]).find('button.checked'); const buttons = $(this.element[0]).find('button.checked');
if(buttons.length === this.nrChoices){ if (buttons.length === this.nrChoices) {
$(event.currentTarget).closest('.window-content').find('.confirm')[0].disabled = false; $(event.currentTarget).closest('.window-content').find('.confirm')[0].disabled = false;
} else { } else {
$(event.currentTarget).closest('.window-content').find('.confirm')[0].disabled = true; $(event.currentTarget).closest('.window-content').find('.confirm')[0].disabled = true;
} }
} };
/** /**
* *
@ -63,27 +63,27 @@ export default class SelectDialog extends Dialog {
*/ */
static async selectItem(data) { static async selectItem(data) {
return this.wait({ return this.wait({
title: data.title ?? "Selection", title: data.title ?? 'Selection',
buttons: { buttons: {
no: { no: {
icon: '<i class="fas fa-times"></i>', icon: '<i class="fas fa-times"></i>',
label: game.i18n.localize("DAGGERHEART.General.Cancel"), label: game.i18n.localize('DAGGERHEART.General.Cancel'),
callback: _ => { callback: _ => {
if(data.cancelMessage){ if (data.cancelMessage) {
ChatMessage.create({content: data.cancelMessage }); ChatMessage.create({ content: data.cancelMessage });
} }
return []; return [];
} }
}, },
confirm: { confirm: {
icon: '<i class="fas fa-check"></i>', icon: '<i class="fas fa-check"></i>',
label: game.i18n.localize("DAGGERHEART.General.OK"), label: game.i18n.localize('DAGGERHEART.General.OK'),
callback: html => { callback: html => {
const buttons = $(html).find('button.checked'); const buttons = $(html).find('button.checked');
return buttons.map(key => Number.parseInt(buttons[key].dataset.index)).toArray(); return buttons.map(key => Number.parseInt(buttons[key].dataset.index)).toArray();
}, },
disabled: true disabled: true
}, }
}, },
choices: data.choices, choices: data.choices,
actor: data.actor, actor: data.actor,

View file

@ -1,27 +1,30 @@
import DamageSelectionDialog from "../applications/damageSelectionDialog.mjs"; import DamageSelectionDialog from '../applications/damageSelectionDialog.mjs';
import NpcRollSelectionDialog from "../applications/npcRollSelectionDialog.mjs"; import NpcRollSelectionDialog from '../applications/npcRollSelectionDialog.mjs';
import RollSelectionDialog from "../applications/rollSelectionDialog.mjs"; import RollSelectionDialog from '../applications/rollSelectionDialog.mjs';
import { GMUpdateEvent, socketEvent } from "../helpers/socket.mjs"; import { GMUpdateEvent, socketEvent } from '../helpers/socket.mjs';
export default class DhpActor extends Actor { export default class DhpActor extends Actor {
_preCreate(data, changes, user){ _preCreate(data, changes, user) {
if(data.type === 'pc'){ if (data.type === 'pc') {
data.prototypeToken = { actorLink: true, disposition: 1, sight: { enabled: true } }; data.prototypeToken = { actorLink: true, disposition: 1, sight: { enabled: true } };
} }
super._preCreate(data, changes, user); super._preCreate(data, changes, user);
} }
prepareData(){ prepareData() {
super.prepareData(); super.prepareData();
} }
async _preUpdate(changed, options, user) { async _preUpdate(changed, options, user) {
//Level Down //Level Down
if(changed.system?.levelData?.changedLevel && this.system.levelData.currentLevel > changed.system.levelData.changedLevel){ if (
changed.system?.levelData?.changedLevel &&
this.system.levelData.currentLevel > changed.system.levelData.changedLevel
) {
changed.system.levelData.currentLevel = changed.system.levelData.changedLevel; changed.system.levelData.currentLevel = changed.system.levelData.changedLevel;
changed.system.levelData.levelups = Object.keys(this.system.levelData.levelups).reduce((acc, x) => { changed.system.levelData.levelups = Object.keys(this.system.levelData.levelups).reduce((acc, x) => {
if(x > changed.system.levelData.currentLevel){ if (x > changed.system.levelData.currentLevel) {
acc[`-=${x}`] = null; acc[`-=${x}`] = null;
} }
@ -29,16 +32,25 @@ export default class DhpActor extends Actor {
}, {}); }, {});
changed.system.attributes = Object.keys(this.system.attributes).reduce((acc, key) => { changed.system.attributes = Object.keys(this.system.attributes).reduce((acc, key) => {
acc[key] = { levelMarks: this.system.attributes[key].levelMarks.filter(x => x <= changed.system.levelData.currentLevel) }; acc[key] = {
levelMarks: this.system.attributes[key].levelMarks.filter(
x => x <= changed.system.levelData.currentLevel
)
};
return acc; return acc;
}, {}); }, {});
changed.system.experiences = this.system.experiences.filter(x => x.level <= changed.system.levelData.currentLevel); changed.system.experiences = this.system.experiences.filter(
x => x.level <= changed.system.levelData.currentLevel
);
if(this.system.multiclass && this.system.multiclass.system.multiclass > changed.system.levelData.changedLevel){ if (
this.system.multiclass &&
this.system.multiclass.system.multiclass > changed.system.levelData.changedLevel
) {
const multiclassFeatures = this.items.filter(x => x.system.multiclass); const multiclassFeatures = this.items.filter(x => x.system.multiclass);
for(var feature of multiclassFeatures){ for (var feature of multiclassFeatures) {
await feature.delete(); await feature.delete();
} }
} }
@ -48,10 +60,9 @@ export default class DhpActor extends Actor {
} }
async diceRoll(modifier, shiftKey) { async diceRoll(modifier, shiftKey) {
if(this.type === 'pc'){ if (this.type === 'pc') {
return await this.dualityRoll(modifier, shiftKey); return await this.dualityRoll(modifier, shiftKey);
} } else {
else {
return await this.npcRoll(modifier, shiftKey); return await this.npcRoll(modifier, shiftKey);
} }
} }
@ -64,10 +75,10 @@ export default class DhpActor extends Actor {
{ {
value: Number.parseInt(modifier.value), value: Number.parseInt(modifier.value),
label: modifier.value >= 0 ? `+${modifier.value}` : `-${modifier.value}`, label: modifier.value >= 0 ? `+${modifier.value}` : `-${modifier.value}`,
title: modifier.title, title: modifier.title
} }
]; ];
if(!shiftKey) { if (!shiftKey) {
const dialogClosed = new Promise((resolve, _) => { const dialogClosed = new Promise((resolve, _) => {
new NpcRollSelectionDialog(this.system.experiences, resolve).render(true); new NpcRollSelectionDialog(this.system.experiences, resolve).render(true);
}); });
@ -75,133 +86,183 @@ export default class DhpActor extends Actor {
nrDice = result.nrDice; nrDice = result.nrDice;
advantage = result.advantage; advantage = result.advantage;
result.experiences.forEach(x => modifiers.push({ value: x.value, label: x.value >= 0 ? `+${x.value}` : `-${x.value}`, title: x.description })) result.experiences.forEach(x =>
modifiers.push({
value: x.value,
label: x.value >= 0 ? `+${x.value}` : `-${x.value}`,
title: x.description
})
);
} }
const roll = new Roll(`${nrDice}d20${advantage === true ? 'kh' : advantage === false ? 'kl': ''} ${modifiers.map(x => `+ ${x.value}`).join(' ')}`); const roll = new Roll(
`${nrDice}d20${advantage === true ? 'kh' : advantage === false ? 'kl' : ''} ${modifiers.map(x => `+ ${x.value}`).join(' ')}`
);
let rollResult = await roll.evaluate(); let rollResult = await roll.evaluate();
const diceResults = rollResult.dice.flatMap(x => x.results.flatMap(result => ({ value: result.result }))); const diceResults = rollResult.dice.flatMap(x => x.results.flatMap(result => ({ value: result.result })));
return { roll, diceResults: diceResults, modifiers: modifiers }; return { roll, diceResults: diceResults, modifiers: modifiers };
} }
async dualityRoll(modifier, shiftKey, bonusDamage=[]){ async dualityRoll(modifier, shiftKey, bonusDamage = []) {
let hopeDice = 'd12', fearDice = 'd12', advantageDice = null, disadvantageDice = null, bonusDamageString = ""; let hopeDice = 'd12',
fearDice = 'd12',
advantageDice = null,
disadvantageDice = null,
bonusDamageString = '';
const modifiers = [ const modifiers = [
{ {
value: modifier.value ? Number.parseInt(modifier.value) : 0, value: modifier.value ? Number.parseInt(modifier.value) : 0,
label: modifier.value >= 0 ? `+${modifier.value}` : `-${modifier.value}`, label: modifier.value >= 0 ? `+${modifier.value}` : `-${modifier.value}`,
title: modifier.title, title: modifier.title
} }
]; ];
if(!shiftKey) { if (!shiftKey) {
const dialogClosed = new Promise((resolve, _) => { const dialogClosed = new Promise((resolve, _) => {
new RollSelectionDialog(this.system.experiences, bonusDamage, this.system.resources.hope.value, resolve).render(true); new RollSelectionDialog(
this.system.experiences,
bonusDamage,
this.system.resources.hope.value,
resolve
).render(true);
}); });
const result = await dialogClosed; const result = await dialogClosed;
hopeDice = result.hope, fearDice = result.fear, advantageDice = result.advantage, disadvantageDice = result.disadvantage; (hopeDice = result.hope),
result.experiences.forEach(x => modifiers.push({ value: x.value, label: x.value >= 0 ? `+${x.value}` : `-${x.value}`, title: x.description })) (fearDice = result.fear),
(advantageDice = result.advantage),
(disadvantageDice = result.disadvantage);
result.experiences.forEach(x =>
modifiers.push({
value: x.value,
label: x.value >= 0 ? `+${x.value}` : `-${x.value}`,
title: x.description
})
);
bonusDamageString = result.bonusDamage; bonusDamageString = result.bonusDamage;
const automateHope = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope); const automateHope = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope);
if(automateHope && result.hopeUsed){ if (automateHope && result.hopeUsed) {
await this.update({ "system.resources.hope.value": this.system.resources.hope.value - result.hopeUsed }); await this.update({
'system.resources.hope.value': this.system.resources.hope.value - result.hopeUsed
});
} }
} }
const roll = new Roll(`1${hopeDice} + 1${fearDice}${advantageDice ? ` + 1${advantageDice}` : disadvantageDice ? ` - 1${disadvantageDice}` : ''} ${modifiers.map(x => `+ ${x.value}`).join(' ')}`); const roll = new Roll(
`1${hopeDice} + 1${fearDice}${advantageDice ? ` + 1${advantageDice}` : disadvantageDice ? ` - 1${disadvantageDice}` : ''} ${modifiers.map(x => `+ ${x.value}`).join(' ')}`
);
let rollResult = await roll.evaluate(); let rollResult = await roll.evaluate();
rollResult.dice[0].options.appearance = { rollResult.dice[0].options.appearance = {
colorset:"inspired", colorset: 'inspired',
foreground: "#FFFFFF", foreground: '#FFFFFF',
background: "#008080", background: '#008080',
outline: "#000000", outline: '#000000',
edge: "#806400", edge: '#806400',
texture: "bloodmoon", texture: 'bloodmoon',
material: "metal", material: 'metal',
font: "Arial Black", font: 'Arial Black',
system: "standard" system: 'standard'
}; };
if(advantageDice || disadvantageDice){ if (advantageDice || disadvantageDice) {
rollResult.dice[1].options.appearance = { rollResult.dice[1].options.appearance = {
colorset:"inspired", colorset: 'inspired',
foreground: disadvantageDice ? "#b30000" : "#FFFFFF", foreground: disadvantageDice ? '#b30000' : '#FFFFFF',
background: "#008080", background: '#008080',
outline: disadvantageDice ? "#000000" : "#000000", outline: disadvantageDice ? '#000000' : '#000000',
edge: "#806400", edge: '#806400',
texture: "bloodmoon", texture: 'bloodmoon',
material: "metal", material: 'metal',
font: "Arial Black", font: 'Arial Black',
system: "standard" system: 'standard'
}; };
rollResult.dice[2].options.appearance = { rollResult.dice[2].options.appearance = {
colorset:"bloodmoon", colorset: 'bloodmoon',
foreground: "#000000", foreground: '#000000',
background: "#430070", background: '#430070',
outline: "#b30000", outline: '#b30000',
edge: "#000000", edge: '#000000',
texture: "bloodmoon", texture: 'bloodmoon',
material: "metal", material: 'metal',
font: "Arial Black", font: 'Arial Black',
system: "standard" system: 'standard'
}; };
} } else {
else {
rollResult.dice[1].options.appearance = { rollResult.dice[1].options.appearance = {
colorset:"bloodmoon", colorset: 'bloodmoon',
foreground: "#000000", foreground: '#000000',
background: "#430070", background: '#430070',
outline: "#b30000", outline: '#b30000',
edge: "#000000", edge: '#000000',
texture: "bloodmoon", texture: 'bloodmoon',
material: "metal", material: 'metal',
font: "Arial Black", font: 'Arial Black',
system: "standard" system: 'standard'
}; };
} }
const hope = rollResult.dice[0].results[0].result; const hope = rollResult.dice[0].results[0].result;
const advantage = advantageDice ? rollResult.dice[1].results[0].result : null; const advantage = advantageDice ? rollResult.dice[1].results[0].result : null;
const disadvantage = disadvantageDice ? rollResult.dice[1].results[0].result : null; const disadvantage = disadvantageDice ? rollResult.dice[1].results[0].result : null;
const fear = advantage || disadvantage ? rollResult.dice[2].results[0].result : rollResult.dice[1].results[0].result; const fear =
advantage || disadvantage ? rollResult.dice[2].results[0].result : rollResult.dice[1].results[0].result;
if(disadvantage){ if (disadvantage) {
rollResult = {...rollResult, total: rollResult.total - Math.max(hope, disadvantage) }; rollResult = { ...rollResult, total: rollResult.total - Math.max(hope, disadvantage) };
} }
if(advantage){ if (advantage) {
rollResult = {...rollResult, total: 'Select Hope Die' }; rollResult = { ...rollResult, total: 'Select Hope Die' };
} }
const automateHope = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope); const automateHope = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope);
if (automateHope && hope > fear){ if (automateHope && hope > fear) {
await this.update({ "system.resources.hope.value": Math.min(this.system.resources.hope.value+1, this.system.resources.hope.max) }); await this.update({
'system.resources.hope.value': Math.min(
this.system.resources.hope.value + 1,
this.system.resources.hope.max
)
});
} }
if(automateHope && hope === fear){ if (automateHope && hope === fear) {
await this.update({ "system.resources": { await this.update({
"hope.value": Math.min(this.system.resources.hope.value+1, this.system.resources.hope.max), 'system.resources': {
"stress.value": Math.max(this.system.resources.stress.value-1, 0), 'hope.value': Math.min(this.system.resources.hope.value + 1, this.system.resources.hope.max),
}}); 'stress.value': Math.max(this.system.resources.stress.value - 1, 0)
}
});
} }
return { roll, rollResult, hope: { dice: hopeDice, value: hope }, fear: { dice: fearDice, value: fear }, advantage: { dice: advantageDice, value: advantage }, disadvantage: { dice: disadvantageDice, value: disadvantage }, modifiers: modifiers, bonusDamageString }; return {
roll,
rollResult,
hope: { dice: hopeDice, value: hope },
fear: { dice: fearDice, value: fear },
advantage: { dice: advantageDice, value: advantage },
disadvantage: { dice: disadvantageDice, value: disadvantage },
modifiers: modifiers,
bonusDamageString
};
} }
async damageRoll(damage, shiftKey){ async damageRoll(damage, shiftKey) {
let rollString = damage.value; let rollString = damage.value;
let bonusDamage = damage.bonusDamage?.filter(x => x.initiallySelected) ?? []; let bonusDamage = damage.bonusDamage?.filter(x => x.initiallySelected) ?? [];
if(!shiftKey) { if (!shiftKey) {
const dialogClosed = new Promise((resolve, _) => { const dialogClosed = new Promise((resolve, _) => {
new DamageSelectionDialog(rollString, bonusDamage, this.system.resources.hope.value, resolve).render(true); new DamageSelectionDialog(rollString, bonusDamage, this.system.resources.hope.value, resolve).render(
true
);
}); });
const result = await dialogClosed; const result = await dialogClosed;
bonusDamage = result.bonusDamage; bonusDamage = result.bonusDamage;
rollString = result.rollString; rollString = result.rollString;
const automateHope = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope); const automateHope = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope);
if(automateHope && result.hopeUsed){ if (automateHope && result.hopeUsed) {
await this.update({ "system.resources.hope.value": this.system.resources.hope.value - result.hopeUsed }); await this.update({
'system.resources.hope.value': this.system.resources.hope.value - result.hopeUsed
});
} }
} }
@ -210,24 +271,21 @@ export default class DhpActor extends Actor {
const dice = []; const dice = [];
const modifiers = []; const modifiers = [];
for(var i = 0; i < rollResult.terms.length; i++){ for (var i = 0; i < rollResult.terms.length; i++) {
const term = rollResult.terms[i]; const term = rollResult.terms[i];
if(term.faces){ if (term.faces) {
dice.push({type: `d${term.faces}`, value: term.total}); dice.push({ type: `d${term.faces}`, value: term.total });
} } else if (term.operator) {
else if (term.operator){ } else if (term.number) {
const operator = i === 0 ? '' : rollResult.terms[i - 1].operator;
}
else if(term.number){
const operator = i === 0 ? '' : rollResult.terms[i-1].operator;
modifiers.push(`${operator}${term.number}`); modifiers.push(`${operator}${term.number}`);
} }
} }
const cls = getDocumentClass("ChatMessage"); const cls = getDocumentClass('ChatMessage');
const msg = new cls({ const msg = new cls({
user: game.user.id, user: game.user.id,
content: await renderTemplate("systems/daggerheart/templates/chat/damage-roll.hbs", { content: await renderTemplate('systems/daggerheart/templates/chat/damage-roll.hbs', {
roll: rollString, roll: rollString,
total: rollResult.total, total: rollResult.total,
dice: dice, dice: dice,
@ -239,16 +297,24 @@ export default class DhpActor extends Actor {
cls.create(msg.toObject()); cls.create(msg.toObject());
} }
async takeDamage(damage, type){ async takeDamage(damage, type) {
const hpDamage = const hpDamage =
damage >= this.system.damageThresholds.severe ? 3 : damage >= this.system.damageThresholds.severe
damage >= this.system.damageThresholds.major ? 2 : ? 3
damage >= this.system.damageThresholds.minor ? 1 : : damage >= this.system.damageThresholds.major
0; ? 2
: damage >= this.system.damageThresholds.minor
? 1
: 0;
const update = { "system.resources.health.value": Math.min(this.system.resources.health.value+hpDamage, this.system.resources.health.max) }; const update = {
'system.resources.health.value': Math.min(
this.system.resources.health.value + hpDamage,
this.system.resources.health.max
)
};
if(game.user.isGM){ if (game.user.isGM) {
await this.update(update); await this.update(update);
} else { } else {
await game.socket.emit(`system.${SYSTEM.id}`, { await game.socket.emit(`system.${SYSTEM.id}`, {
@ -256,24 +322,24 @@ export default class DhpActor extends Actor {
data: { data: {
action: GMUpdateEvent.UpdateDocument, action: GMUpdateEvent.UpdateDocument,
uuid: this.uuid, uuid: this.uuid,
update: update, update: update
} }
}); });
} }
} }
async takeHealing(healing, type) { async takeHealing(healing, type) {
let update = { }; let update = {};
switch(type){ switch (type) {
case SYSTEM.GENERAL.healingTypes.health.id: case SYSTEM.GENERAL.healingTypes.health.id:
update = { "system.resources.health.value": Math.max(this.system.resources.health.value - healing, 0) }; update = { 'system.resources.health.value': Math.max(this.system.resources.health.value - healing, 0) };
break; break;
case SYSTEM.GENERAL.healingTypes.stress.id: case SYSTEM.GENERAL.healingTypes.stress.id:
update = { "system.resources.stress.value": Math.max(this.system.resources.stress.value - healing, 0) }; update = { 'system.resources.stress.value': Math.max(this.system.resources.stress.value - healing, 0) };
break; break;
} }
if(game.user.isGM){ if (game.user.isGM) {
await this.update(update); await this.update(update);
} else { } else {
await game.socket.emit(`system.${SYSTEM.id}`, { await game.socket.emit(`system.${SYSTEM.id}`, {
@ -281,67 +347,67 @@ export default class DhpActor extends Actor {
data: { data: {
action: GMUpdateEvent.UpdateDocument, action: GMUpdateEvent.UpdateDocument,
uuid: this.uuid, uuid: this.uuid,
update: update, update: update
} }
}); });
} }
} }
async emulateItemDrop(data) { async emulateItemDrop(data) {
const event = new DragEvent("drop", { altKey: game.keyboard.isModifierActive("Alt") }); const event = new DragEvent('drop', { altKey: game.keyboard.isModifierActive('Alt') });
return this.sheet._onDropItem(event, { data: data }); return this.sheet._onDropItem(event, { data: data });
} }
//Move to action-scope? //Move to action-scope?
async useAction(action) { async useAction(action) {
const userTargets = Array.from(game.user.targets); const userTargets = Array.from(game.user.targets);
const otherTarget = action.target.type ===SYSTEM.ACTIONS.targetTypes.other.id; const otherTarget = action.target.type === SYSTEM.ACTIONS.targetTypes.other.id;
if(otherTarget && userTargets.length === 0) { if (otherTarget && userTargets.length === 0) {
ui.notifications.error(game.i18n.localize("DAGGERHEART.Notification.Error.ActionRequiresTarget")); ui.notifications.error(game.i18n.localize('DAGGERHEART.Notification.Error.ActionRequiresTarget'));
return; return;
} }
if(action.cost.type != null && action.cost.value != null){ if (action.cost.type != null && action.cost.value != null) {
if (this.system.resources[action.cost.type].value < action.cost.value-1) { if (this.system.resources[action.cost.type].value < action.cost.value - 1) {
ui.notifications.error(game.i18n.localize(`Insufficient ${action.cost.type} to use this ability`)); ui.notifications.error(game.i18n.localize(`Insufficient ${action.cost.type} to use this ability`));
return; return;
} }
} }
// const targets = otherTarget ? userTargets : [game.user.character]; // const targets = otherTarget ? userTargets : [game.user.character];
if(action.damage.type){ if (action.damage.type) {
let roll = { formula: action.damage.value, result: action.damage.value }; let roll = { formula: action.damage.value, result: action.damage.value };
if(Number.isNaN(Number.parseInt(action.damage.value))){ if (Number.isNaN(Number.parseInt(action.damage.value))) {
roll = await new Roll(`1${action.damage.value}`).evaluate(); roll = await new Roll(`1${action.damage.value}`).evaluate();
} }
const cls = getDocumentClass("ChatMessage"); const cls = getDocumentClass('ChatMessage');
const msg = new cls({ const msg = new cls({
user: game.user.id, user: game.user.id,
content: await renderTemplate("systems/daggerheart/templates/chat/damage-roll.hbs", { content: await renderTemplate('systems/daggerheart/templates/chat/damage-roll.hbs', {
roll: roll.formula, roll: roll.formula,
total: roll.result, total: roll.result,
type: action.damage.type, type: action.damage.type
}), })
}); });
cls.create(msg.toObject()); cls.create(msg.toObject());
} }
if(action.healing.type){ if (action.healing.type) {
let roll = { formula: action.healing.value, result: action.healing.value }; let roll = { formula: action.healing.value, result: action.healing.value };
if(Number.isNaN(Number.parseInt(action.healing.value))){ if (Number.isNaN(Number.parseInt(action.healing.value))) {
roll = await new Roll(`1${action.healing.value}`).evaluate(); roll = await new Roll(`1${action.healing.value}`).evaluate();
} }
const cls = getDocumentClass("ChatMessage"); const cls = getDocumentClass('ChatMessage');
const msg = new cls({ const msg = new cls({
user: game.user.id, user: game.user.id,
content: await renderTemplate("systems/daggerheart/templates/chat/healing-roll.hbs", { content: await renderTemplate('systems/daggerheart/templates/chat/healing-roll.hbs', {
roll: roll.formula, roll: roll.formula,
total: roll.result, total: roll.result,
type: action.healing.type, type: action.healing.type
}), })
}); });
cls.create(msg.toObject()); cls.create(msg.toObject());

View file

@ -1,8 +1,8 @@
import { GMUpdateEvent, socketEvent } from "../helpers/socket.mjs"; import { GMUpdateEvent, socketEvent } from '../helpers/socket.mjs';
export default class DhpCombat extends Combat { export default class DhpCombat extends Combat {
_sortCombatants(a, b) { _sortCombatants(a, b) {
if(a.isNPC !== b.isNPC){ if (a.isNPC !== b.isNPC) {
const aVal = a.isNPC ? 0 : 1; const aVal = a.isNPC ? 0 : 1;
const bVal = b.isNPC ? 0 : 1; const bVal = b.isNPC ? 0 : 1;
@ -13,20 +13,23 @@ export default class DhpCombat extends Combat {
} }
async useActionToken(combatantId) { async useActionToken(combatantId) {
const automateActionPoints = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.ActionPoints); const automateActionPoints = await game.settings.get(
SYSTEM.id,
SYSTEM.SETTINGS.gameSettings.Automation.ActionPoints
);
if(game.user.isGM){ if (game.user.isGM) {
if(this.system.actions < 1) return; if (this.system.actions < 1) return;
const update = automateActionPoints ? const update = automateActionPoints
{ "system.activeCombatant": combatantId, "system.actions": Math.max(this.system.actions-1, 0) } : ? { 'system.activeCombatant': combatantId, 'system.actions': Math.max(this.system.actions - 1, 0) }
{ "system.activeCombatant": combatantId }; : { 'system.activeCombatant': combatantId };
await this.update(update); await this.update(update);
} else { } else {
const update = automateActionPoints ? const update = automateActionPoints
{ "system.activeCombatant": combatantId, "system.actions": this.system.actions+1} : ? { 'system.activeCombatant': combatantId, 'system.actions': this.system.actions + 1 }
{ "system.activeCombatant": combatantId }; : { 'system.activeCombatant': combatantId };
await game.socket.emit(`system.${SYSTEM.id}`, { await game.socket.emit(`system.${SYSTEM.id}`, {
action: socketEvent.GMUpdate, action: socketEvent.GMUpdate,

View file

@ -1,18 +1,18 @@
export default class DhpItem extends Item { export default class DhpItem extends Item {
_preCreate(data, changes, user){ _preCreate(data, changes, user) {
super._preCreate(data, changes, user); super._preCreate(data, changes, user);
} }
prepareData(){ prepareData() {
super.prepareData(); super.prepareData();
if(this.type === 'class'){ if (this.type === 'class') {
// Bad. Make this better. // Bad. Make this better.
// this.system.domains = CONFIG.daggerheart.DOMAIN.classDomainMap[Object.keys(CONFIG.daggerheart.DOMAIN.classDomainMap).find(x => x === this.name.toLowerCase())]; // this.system.domains = CONFIG.daggerheart.DOMAIN.classDomainMap[Object.keys(CONFIG.daggerheart.DOMAIN.classDomainMap).find(x => x === this.name.toLowerCase())];
} }
} }
isInventoryItem(){ isInventoryItem() {
return ['weapon', 'armor', 'miscellaneous', 'consumable'].includes(this.type); return ['weapon', 'armor', 'miscellaneous', 'consumable'].includes(this.type);
} }
@ -24,13 +24,13 @@ export default class DhpItem extends Item {
const documentName = this.metadata.name; const documentName = this.metadata.name;
const types = game.documentTypes[documentName].filter(t => t !== CONST.BASE_DOCUMENT_TYPE); const types = game.documentTypes[documentName].filter(t => t !== CONST.BASE_DOCUMENT_TYPE);
let collection; let collection;
if ( !parent ) { if (!parent) {
if ( pack ) collection = game.packs.get(pack); if (pack) collection = game.packs.get(pack);
else collection = game.collections.get(documentName); else collection = game.collections.get(documentName);
} }
const folders = collection?._formatFolderSelectOptions() ?? []; const folders = collection?._formatFolderSelectOptions() ?? [];
const label = game.i18n.localize(this.metadata.label); const label = game.i18n.localize(this.metadata.label);
const title = game.i18n.format("DOCUMENT.Create", {type: label}); const title = game.i18n.format('DOCUMENT.Create', { type: label });
const typeObjects = types.reduce((obj, t) => { const typeObjects = types.reduce((obj, t) => {
const label = CONFIG[documentName]?.typeLabels?.[t] ?? t; const label = CONFIG[documentName]?.typeLabels?.[t] ?? t;
obj[t] = { value: t, label: game.i18n.has(label) ? game.i18n.localize(label) : t }; obj[t] = { value: t, label: game.i18n.has(label) ? game.i18n.localize(label) : t };
@ -38,15 +38,22 @@ export default class DhpItem extends Item {
}, {}); }, {});
// Render the document creation form // Render the document creation form
const html = await renderTemplate("systems/daggerheart/templates/sidebar/documentCreate.hbs", { const html = await renderTemplate('systems/daggerheart/templates/sidebar/documentCreate.hbs', {
folders, folders,
name: data.name || game.i18n.format("DOCUMENT.New", {type: label}), name: data.name || game.i18n.format('DOCUMENT.New', { type: label }),
folder: data.folder, folder: data.folder,
hasFolders: folders.length >= 1, hasFolders: folders.length >= 1,
type: data.type || CONFIG[documentName]?.defaultType || typeObjects.armor, type: data.type || CONFIG[documentName]?.defaultType || typeObjects.armor,
types: { types: {
Items: [typeObjects.armor, typeObjects.weapon, typeObjects.consumable, typeObjects.miscellaneous], Items: [typeObjects.armor, typeObjects.weapon, typeObjects.consumable, typeObjects.miscellaneous],
Character: [typeObjects.class, typeObjects.subclass, typeObjects.ancestry, typeObjects.community, typeObjects.feature, typeObjects.domainCard], Character: [
typeObjects.class,
typeObjects.subclass,
typeObjects.ancestry,
typeObjects.community,
typeObjects.feature,
typeObjects.domainCard
]
}, },
hasTypes: types.length > 1 hasTypes: types.length > 1
}); });
@ -57,16 +64,16 @@ export default class DhpItem extends Item {
content: html, content: html,
label: title, label: title,
callback: html => { callback: html => {
const form = html[0].querySelector("form"); const form = html[0].querySelector('form');
const fd = new FormDataExtended(form); const fd = new FormDataExtended(form);
foundry.utils.mergeObject(data, fd.object, {inplace: true}); foundry.utils.mergeObject(data, fd.object, { inplace: true });
if ( !data.folder ) delete data.folder; if (!data.folder) delete data.folder;
if ( types.length === 1 ) data.type = types[0]; if (types.length === 1) data.type = types[0];
if ( !data.name?.trim() ) data.name = this.defaultName(); if (!data.name?.trim()) data.name = this.defaultName();
return this.create(data, {parent, pack, renderSheet: true}); return this.create(data, { parent, pack, renderSheet: true });
}, },
rejectClose: false, rejectClose: false,
options options
}); });
} }
} }

View file

@ -1,7 +1,7 @@
import { getWidthOfText } from "./utils.mjs"; import { getWidthOfText } from './utils.mjs';
export default class RegisterHandlebarsHelpers { export default class RegisterHandlebarsHelpers {
static registerHelpers(){ static registerHelpers() {
Handlebars.registerHelper({ Handlebars.registerHelper({
looseEq: this.looseEq, looseEq: this.looseEq,
times: this.times, times: this.times,
@ -11,60 +11,62 @@ export default class RegisterHandlebarsHelpers {
objectSelector: this.objectSelector, objectSelector: this.objectSelector,
includes: this.includes, includes: this.includes,
simpleEditor: this.simpleEditor, simpleEditor: this.simpleEditor,
debug: this.debug, debug: this.debug
}); });
}; }
static looseEq(a, b){ static looseEq(a, b) {
return a == b; return a == b;
} }
static times(nr, block){ static times(nr, block) {
var accum = ''; var accum = '';
for(var i = 0; i < nr; ++i) for (var i = 0; i < nr; ++i) accum += block.fn(i);
accum += block.fn(i);
return accum; return accum;
} }
static join(...options){ static join(...options) {
return options.slice(0, options.length-1); return options.slice(0, options.length - 1);
} }
static add(a, b){ static add(a, b) {
const aNum = Number.parseInt(a); const aNum = Number.parseInt(a);
const bNum = Number.parseInt(b); const bNum = Number.parseInt(b);
return (Number.isNaN(aNum) ? 0 : aNum) + (Number.isNaN(bNum) ? 0 : bNum); return (Number.isNaN(aNum) ? 0 : aNum) + (Number.isNaN(bNum) ? 0 : bNum);
} }
static subtract(a, b){ static subtract(a, b) {
const aNum = Number.parseInt(a); const aNum = Number.parseInt(a);
const bNum = Number.parseInt(b); const bNum = Number.parseInt(b);
return (Number.isNaN(aNum) ? 0 : aNum) - (Number.isNaN(bNum) ? 0 : bNum); return (Number.isNaN(aNum) ? 0 : aNum) - (Number.isNaN(bNum) ? 0 : bNum);
} }
static objectSelector(options){ static objectSelector(options) {
let { title, values, titleFontSize, ids, style } = options.hash; let { title, values, titleFontSize, ids, style } = options.hash;
const titleLength = getWidthOfText(title, titleFontSize, true, true); const titleLength = getWidthOfText(title, titleFontSize, true, true);
const margins = 12; const margins = 12;
const buttons = options.fn(); const buttons = options.fn();
const nrButtons = Math.max($(buttons).length-1, 1); const nrButtons = Math.max($(buttons).length - 1, 1);
const iconWidth = 26; const iconWidth = 26;
const texts = values.reduce((acc, x, index) => { const texts = values
if(x){ .reduce((acc, x, index) => {
acc.push(`<span class="object-select-item" data-action="viewObject" data-value="${ids[index]}">${x}</span>`); if (x) {
acc.push(
`<span class="object-select-item" data-action="viewObject" data-value="${ids[index]}">${x}</span>`
);
} }
return acc; return acc;
}, []).join(' '); }, [])
.join(' ');
const html = const html = `<div ${style ? 'style="' + style + '"' : ''}">
`<div ${style ? 'style="'+style+'"' : ''}">
<div class="object-select-display iconbar"> <div class="object-select-display iconbar">
<span class="object-select-title">${title}</span> <span class="object-select-title">${title}</span>
<div class="object-select-text" style="padding-left: ${titleLength+margins}px; padding-right: ${nrButtons*iconWidth}px;"> <div class="object-select-text" style="padding-left: ${titleLength + margins}px; padding-right: ${nrButtons * iconWidth}px;">
${texts} ${texts}
</div> </div>
${buttons} ${buttons}
@ -76,25 +78,31 @@ export default class RegisterHandlebarsHelpers {
} }
static rangePicker(options) { static rangePicker(options) {
let {name, value, min, max, step} = options.hash; let { name, value, min, max, step } = options.hash;
name = name || "range"; name = name || 'range';
value = value ?? ""; value = value ?? '';
if ( Number.isNaN(value) ) value = ""; if (Number.isNaN(value)) value = '';
const html = const html = `<input type="range" name="${name}" value="${value}" min="${min}" max="${max}" step="${step}"/>
`<input type="range" name="${name}" value="${value}" min="${min}" max="${max}" step="${step}"/>
<span class="range-value">${value}</span>`; <span class="range-value">${value}</span>`;
return new Handlebars.SafeString(html); return new Handlebars.SafeString(html);
} }
static includes(list, item){ static includes(list, item) {
return list.includes(item); return list.includes(item);
} }
static simpleEditor(content, options) { static simpleEditor(content, options) {
const { target, editable=true, button, engine="tinymce", collaborate=false, class: cssClass } = options.hash; const {
const config = {name: target, value: content, button, collaborate, editable, engine}; target,
editable = true,
button,
engine = 'tinymce',
collaborate = false,
class: cssClass
} = options.hash;
const config = { name: target, value: content, button, collaborate, editable, engine };
const element = foundry.applications.fields.createEditorInput(config); const element = foundry.applications.fields.createEditorInput(config);
if ( cssClass ) element.querySelector(".editor-content").classList.add(cssClass); if (cssClass) element.querySelector('.editor-content').classList.add(cssClass);
return new Handlebars.SafeString(element.outerHTML); return new Handlebars.SafeString(element.outerHTML);
} }

View file

@ -1,4 +1,4 @@
export function handleSocketEvent({action=null, data={}}={}) { export function handleSocketEvent({ action = null, data = {} } = {}) {
switch (action) { switch (action) {
case socketEvent.GMUpdate: case socketEvent.GMUpdate:
Hooks.callAll(socketEvent.GMUpdate, data.action, data.uuid, data.update); Hooks.callAll(socketEvent.GMUpdate, data.action, data.uuid, data.update);
@ -10,11 +10,11 @@ export function handleSocketEvent({action=null, data={}}={}) {
} }
export const socketEvent = { export const socketEvent = {
GMUpdate: "DhpGMUpdate", GMUpdate: 'DhpGMUpdate',
DhpFearUpdate: "DhpFearUpdate", DhpFearUpdate: 'DhpFearUpdate'
}; };
export const GMUpdateEvent = { export const GMUpdateEvent = {
UpdateDocument: "DhpGMUpdateDocument", UpdateDocument: 'DhpGMUpdateDocument',
UpdateFear: "DhpUpdateFear" UpdateFear: 'DhpUpdateFear'
}; };

View file

@ -1,7 +1,7 @@
export const loadCompendiumOptions = async (compendiums) => { export const loadCompendiumOptions = async compendiums => {
const compendiumValues = []; const compendiumValues = [];
for(var compendium of compendiums){ for (var compendium of compendiums) {
const values = await getCompendiumOptions(compendium); const values = await getCompendiumOptions(compendium);
compendiumValues.push(values); compendiumValues.push(values);
} }
@ -9,11 +9,11 @@ export const loadCompendiumOptions = async (compendiums) => {
return compendiumValues; return compendiumValues;
}; };
const getCompendiumOptions = async (compendium) => { const getCompendiumOptions = async compendium => {
const compendiumPack = await game.packs.get(compendium); const compendiumPack = await game.packs.get(compendium);
const values = []; const values = [];
for(var value of compendiumPack.index){ for (var value of compendiumPack.index) {
const document = await compendiumPack.getDocument(value._id); const document = await compendiumPack.getDocument(value._id);
values.push(document); values.push(document);
} }
@ -34,23 +34,22 @@ export const getWidthOfText = (txt, fontsize, allCaps, bold) => {
// getWidthOfText.e.innerText = txt; // getWidthOfText.e.innerText = txt;
// return getWidthOfText.e.offsetWidth; // return getWidthOfText.e.offsetWidth;
const text = allCaps ? txt.toUpperCase() : txt; const text = allCaps ? txt.toUpperCase() : txt;
if(getWidthOfText.c === undefined){ if (getWidthOfText.c === undefined) {
getWidthOfText.c=document.createElement('canvas'); getWidthOfText.c = document.createElement('canvas');
getWidthOfText.ctx=getWidthOfText.c.getContext('2d'); getWidthOfText.ctx = getWidthOfText.c.getContext('2d');
} }
var fontspec = `${bold ? 'bold': ''} ${fontsize}px` + ' ' + 'Signika, sans-serif'; var fontspec = `${bold ? 'bold' : ''} ${fontsize}px` + ' ' + 'Signika, sans-serif';
if(getWidthOfText.ctx.font !== fontspec) if (getWidthOfText.ctx.font !== fontspec) getWidthOfText.ctx.font = fontspec;
getWidthOfText.ctx.font = fontspec;
return getWidthOfText.ctx.measureText(text).width; return getWidthOfText.ctx.measureText(text).width;
} };
export const padArray = (arr, len, fill) => { export const padArray = (arr, len, fill) => {
return arr.concat(Array(len).fill(fill)).slice(0,len); return arr.concat(Array(len).fill(fill)).slice(0, len);
} };
export const getTier = (level, asNr) => { export const getTier = (level, asNr) => {
switch(Math.floor((level+1)/3)){ switch (Math.floor((level + 1) / 3)) {
case 1: case 1:
return asNr ? 1 : 'tier1'; return asNr ? 1 : 'tier1';
case 2: case 2:
@ -60,23 +59,26 @@ export const getTier = (level, asNr) => {
default: default:
return asNr ? 0 : 'tier0'; return asNr ? 0 : 'tier0';
} }
} };
export const capitalize = (string) => { export const capitalize = string => {
return string.charAt(0).toUpperCase() + string.slice(1); return string.charAt(0).toUpperCase() + string.slice(1);
} };
export const getPathValue = (path, entity, numeric) => { export const getPathValue = (path, entity, numeric) => {
const pathValue = foundry.utils.getProperty(entity, path); const pathValue = foundry.utils.getProperty(entity, path);
if(pathValue) return numeric ? Number.parseInt(pathValue) : pathValue; if (pathValue) return numeric ? Number.parseInt(pathValue) : pathValue;
return numeric ? Number.parseInt(path) : path; return numeric ? Number.parseInt(path) : path;
}; };
export const generateId = (title, length) => { export const generateId = (title, length) => {
const id = title.split(" ").map((w, i) => { const id = title
const p = w.slugify({replacement: "", strict: true}); .split(' ')
.map((w, i) => {
const p = w.slugify({ replacement: '', strict: true });
return i ? p.titleCase() : p; return i ? p.titleCase() : p;
}).join(""); })
return Number.isNumeric(length) ? id.slice(0, length).padEnd(length, "0") : id; .join('');
} return Number.isNumeric(length) ? id.slice(0, length).padEnd(length, '0') : id;
};

View file

@ -1,5 +1,5 @@
export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLog { export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLog {
constructor(){ constructor() {
super(); super();
this.targetTemplate = { this.targetTemplate = {
@ -9,27 +9,37 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
minimizedSheets: [], minimizedSheets: [],
config: undefined, config: undefined,
targets: undefined targets: undefined
} };
this.setupHooks(); this.setupHooks();
} }
addChatListeners = async (app, html, data) => { addChatListeners = async (app, html, data) => {
html.querySelectorAll('.roll-damage-button').forEach(element => element.addEventListener('click', event => this.onRollDamage(event, data.message))); html.querySelectorAll('.roll-damage-button').forEach(element =>
html.querySelectorAll('.target-container').forEach(element => element.addEventListener('hover', hover(this.hoverTarget, this.unhoverTarget))); // ???? element.addEventListener('click', event => this.onRollDamage(event, data.message))
);
html.querySelectorAll('.target-container').forEach(element =>
element.addEventListener('hover', hover(this.hoverTarget, this.unhoverTarget))
); // ????
// html.find('.target-container').mouseout(this.unhoverTarget); // html.find('.target-container').mouseout(this.unhoverTarget);
html.querySelectorAll('.damage-button').forEach(element => element.addEventListener('click', this.onDamage)); html.querySelectorAll('.damage-button').forEach(element => element.addEventListener('click', this.onDamage));
html.querySelectorAll('.healing-button').forEach(element => element.addEventListener('click', this.onHealing)); html.querySelectorAll('.healing-button').forEach(element => element.addEventListener('click', this.onHealing));
html.querySelectorAll('.target-indicator').forEach(element => element.addEventListener('click', this.onToggleTargets)); html.querySelectorAll('.target-indicator').forEach(element =>
element.addEventListener('click', this.onToggleTargets)
);
html.querySelectorAll('.advantage').forEach(element => element.hover(this.hoverAdvantage)); // ?? html.querySelectorAll('.advantage').forEach(element => element.hover(this.hoverAdvantage)); // ??
html.querySelectorAll('.advantage').forEach(element => element.addEventListener('click', event => this.selectAdvantage.bind(this)(event, data.message))); html.querySelectorAll('.advantage').forEach(element =>
html.querySelectorAll('.ability-use-button').forEach(element => element.addEventListener('click', this.abilityUseButton.bind(this)(event, data.message))); element.addEventListener('click', event => this.selectAdvantage.bind(this)(event, data.message))
} );
html.querySelectorAll('.ability-use-button').forEach(element =>
element.addEventListener('click', this.abilityUseButton.bind(this)(event, data.message))
);
};
setupHooks(){ setupHooks() {
Hooks.on('renderChatMessageHTML', this.addChatListeners.bind()); Hooks.on('renderChatMessageHTML', this.addChatListeners.bind());
} }
close(options){ close(options) {
Hooks.off('renderChatMessageHTML', this.addChatListeners); Hooks.off('renderChatMessageHTML', this.addChatListeners);
super.close(options); super.close(options);
} }
@ -40,47 +50,49 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
await game.user.character.damageRoll(message.system.damage, event.shiftKey); await game.user.character.damageRoll(message.system.damage, event.shiftKey);
}; };
hoverTarget = (event) => { hoverTarget = event => {
event.stopPropagation(); event.stopPropagation();
const token = canvas.tokens.get(event.currentTarget.dataset.token); const token = canvas.tokens.get(event.currentTarget.dataset.token);
if ( !token.controlled ) token._onHoverIn(event, {hoverOutOthers: true}); if (!token.controlled) token._onHoverIn(event, { hoverOutOthers: true });
}
unhoverTarget = (event) => {
const token = canvas.tokens.get(event.currentTarget.dataset.token);
if ( !token.controlled ) token._onHoverOut(event);
}; };
onDamage = async (event) => { unhoverTarget = event => {
const token = canvas.tokens.get(event.currentTarget.dataset.token);
if (!token.controlled) token._onHoverOut(event);
};
onDamage = async event => {
event.stopPropagation(); event.stopPropagation();
const damage = Number.parseInt(event.currentTarget.dataset.value); const damage = Number.parseInt(event.currentTarget.dataset.value);
const targets = Array.from(game.user.targets); const targets = Array.from(game.user.targets);
if(targets.length === 0) ui.notifications.info(game.i18n.localize("DAGGERHEART.Notification.Info.NoTargetsSelected")); if (targets.length === 0)
ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.NoTargetsSelected'));
for(var target of targets){ for (var target of targets) {
await target.actor.takeDamage(damage, event.currentTarget.dataset.type); await target.actor.takeDamage(damage, event.currentTarget.dataset.type);
} }
}; };
onHealing = async (event) => { onHealing = async event => {
event.stopPropagation(); event.stopPropagation();
const healing = Number.parseInt(event.currentTarget.dataset.value); const healing = Number.parseInt(event.currentTarget.dataset.value);
const targets = Array.from(game.user.targets); const targets = Array.from(game.user.targets);
if(targets.length === 0) ui.notifications.info(game.i18n.localize("DAGGERHEART.Notification.Info.NoTargetsSelected")); if (targets.length === 0)
ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.NoTargetsSelected'));
for(var target of targets){ for (var target of targets) {
await target.actor.takeHealing(healing, event.currentTarget.dataset.type); await target.actor.takeHealing(healing, event.currentTarget.dataset.type);
} }
} };
onToggleTargets = async (event) => { onToggleTargets = async event => {
event.stopPropagation(); event.stopPropagation();
$($(event.currentTarget).parent()).find('.target-container').toggleClass('hidden'); $($(event.currentTarget).parent()).find('.target-container').toggleClass('hidden');
}; };
hoverAdvantage = (event) => { hoverAdvantage = event => {
$(event.currentTarget).siblings('.advantage').toggleClass('unused'); $(event.currentTarget).siblings('.advantage').toggleClass('unused');
}; };
@ -88,16 +100,16 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
event.stopPropagation(); event.stopPropagation();
const updateMessage = game.messages.get(message._id); const updateMessage = game.messages.get(message._id);
await updateMessage.update({ system: { advantageSelected: event.currentTarget.id === 'hope' ? 1 : 2 }}); await updateMessage.update({ system: { advantageSelected: event.currentTarget.id === 'hope' ? 1 : 2 } });
$(event.currentTarget).siblings('.advantage').off('click'); $(event.currentTarget).siblings('.advantage').off('click');
$(event.currentTarget).off('click'); $(event.currentTarget).off('click');
} };
abilityUseButton = async (event, message) => { abilityUseButton = async (event, message) => {
event.stopPropagation(); event.stopPropagation();
const action = message.system.actions[Number.parseInt(event.currentTarget.dataset.index)]; const action = message.system.actions[Number.parseInt(event.currentTarget.dataset.index)];
await game.user.character.useAction(action); await game.user.character.useAction(action);
} };
} }

View file

@ -1,4 +1,4 @@
import { GMUpdateEvent, socketEvent } from "../helpers/socket.mjs"; import { GMUpdateEvent, socketEvent } from '../helpers/socket.mjs';
export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.CombatTracker { export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.CombatTracker {
constructor(data, context) { constructor(data, context) {
@ -7,68 +7,68 @@ export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.
Hooks.on(socketEvent.DhpFearUpdate, this.onFearUpdate); Hooks.on(socketEvent.DhpFearUpdate, this.onFearUpdate);
} }
get template(){ get template() {
return 'systems/daggerheart/templates/ui/combatTracker.hbs'; return 'systems/daggerheart/templates/ui/combatTracker.hbs';
} }
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
html.on("click", ".token-action-tokens .use-action-token", this.useActionToken.bind(this)); html.on('click', '.token-action-tokens .use-action-token', this.useActionToken.bind(this));
html.on("click", ".encounter-gm-resources .trade-actions", this.tradeActions.bind(this)); html.on('click', '.encounter-gm-resources .trade-actions', this.tradeActions.bind(this));
html.on("click", ".encounter-gm-resources .trade-fear", this.tradeFear.bind(this)); html.on('click', '.encounter-gm-resources .trade-fear', this.tradeFear.bind(this));
html.on("click", ".encounter-gm-resources .icon-button.up", this.increaseResource.bind(this)); html.on('click', '.encounter-gm-resources .icon-button.up', this.increaseResource.bind(this));
html.on("click", ".encounter-gm-resources .icon-button.down", this.decreaseResource.bind(this)); html.on('click', '.encounter-gm-resources .icon-button.down', this.decreaseResource.bind(this));
} }
async useActionToken(event){ async useActionToken(event) {
event.stopPropagation(); event.stopPropagation();
const combatant = event.currentTarget.dataset.combatant; const combatant = event.currentTarget.dataset.combatant;
await game.combat.useActionToken(combatant); await game.combat.useActionToken(combatant);
} }
async tradeActions(event){ async tradeActions(event) {
if(event.currentTarget.classList.contains('disabled')) return; if (event.currentTarget.classList.contains('disabled')) return;
const currentFear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear); const currentFear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear);
const value = currentFear+1; const value = currentFear + 1;
if(value <= 6){ if (value <= 6) {
Hooks.callAll(socketEvent.GMUpdate,GMUpdateEvent.UpdateFear, null, value); Hooks.callAll(socketEvent.GMUpdate, GMUpdateEvent.UpdateFear, null, value);
await game.socket.emit(`system.${SYSTEM.id}`, { await game.socket.emit(`system.${SYSTEM.id}`, {
action: socketEvent.GMUpdate, action: socketEvent.GMUpdate,
data: { action: GMUpdateEvent.UpdateFear, update: value }, data: { action: GMUpdateEvent.UpdateFear, update: value }
}); });
await game.combat.update({ "system.actions": game.combat.system.actions-2 }); await game.combat.update({ 'system.actions': game.combat.system.actions - 2 });
} }
} }
async tradeFear(){ async tradeFear() {
if(event.currentTarget.classList.contains('disabled')) return; if (event.currentTarget.classList.contains('disabled')) return;
const currentFear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear); const currentFear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear);
const value = currentFear-1; const value = currentFear - 1;
if(value >= 0){ if (value >= 0) {
Hooks.callAll(socketEvent.GMUpdate,GMUpdateEvent.UpdateFear, null, value); Hooks.callAll(socketEvent.GMUpdate, GMUpdateEvent.UpdateFear, null, value);
await game.socket.emit(`system.${SYSTEM.id}`, { await game.socket.emit(`system.${SYSTEM.id}`, {
action: socketEvent.GMUpdate, action: socketEvent.GMUpdate,
data: { action: GMUpdateEvent.UpdateFear, update: value }, data: { action: GMUpdateEvent.UpdateFear, update: value }
}); });
await game.combat.update({ "system.actions": game.combat.system.actions+2 }); await game.combat.update({ 'system.actions': game.combat.system.actions + 2 });
} }
} }
async increaseResource(event) { async increaseResource(event) {
if(event.currentTarget.dataset.type === 'action'){ if (event.currentTarget.dataset.type === 'action') {
await game.combat.update({ "system.actions": game.combat.system.actions+1 }); await game.combat.update({ 'system.actions': game.combat.system.actions + 1 });
} }
const currentFear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear); const currentFear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear);
const value = currentFear+1; const value = currentFear + 1;
if(event.currentTarget.dataset.type === 'fear' && value <= 6){ if (event.currentTarget.dataset.type === 'fear' && value <= 6) {
Hooks.callAll(socketEvent.GMUpdate,GMUpdateEvent.UpdateFear, null, value); Hooks.callAll(socketEvent.GMUpdate, GMUpdateEvent.UpdateFear, null, value);
await game.socket.emit(`system.${SYSTEM.id}`, { await game.socket.emit(`system.${SYSTEM.id}`, {
action: socketEvent.GMUpdate, action: socketEvent.GMUpdate,
data: { action: GMUpdateEvent.UpdateFear, update: value }, data: { action: GMUpdateEvent.UpdateFear, update: value }
}); });
} }
@ -76,24 +76,24 @@ export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.
} }
async decreaseResource(event) { async decreaseResource(event) {
if(event.currentTarget.dataset.type === 'action' && game.combat.system.actions-1 >= 0){ if (event.currentTarget.dataset.type === 'action' && game.combat.system.actions - 1 >= 0) {
await game.combat.update({ "system.actions": game.combat.system.actions-1 }); await game.combat.update({ 'system.actions': game.combat.system.actions - 1 });
} }
const currentFear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear); const currentFear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear);
const value = currentFear-1; const value = currentFear - 1;
if(event.currentTarget.dataset.type === 'fear' && value >= 0){ if (event.currentTarget.dataset.type === 'fear' && value >= 0) {
Hooks.callAll(socketEvent.GMUpdate,GMUpdateEvent.UpdateFear, null, value); Hooks.callAll(socketEvent.GMUpdate, GMUpdateEvent.UpdateFear, null, value);
await game.socket.emit(`system.${SYSTEM.id}`, { await game.socket.emit(`system.${SYSTEM.id}`, {
action: socketEvent.GMUpdate, action: socketEvent.GMUpdate,
data: { action: GMUpdateEvent.UpdateFear, update: value }, data: { action: GMUpdateEvent.UpdateFear, update: value }
}); });
} }
this.render(); this.render();
} }
async getData(options={}) { async getData(options = {}) {
let context = await super.getData(options); let context = await super.getData(options);
// Get the combat encounters possible for the viewed Scene // Get the combat encounters possible for the viewed Scene
@ -101,9 +101,9 @@ export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.
const hasCombat = combat !== null; const hasCombat = combat !== null;
const combats = this.combats; const combats = this.combats;
const currentIdx = combats.findIndex(c => c === combat); const currentIdx = combats.findIndex(c => c === combat);
const previousId = currentIdx > 0 ? combats[currentIdx-1].id : null; const previousId = currentIdx > 0 ? combats[currentIdx - 1].id : null;
const nextId = currentIdx < combats.length - 1 ? combats[currentIdx+1].id : null; const nextId = currentIdx < combats.length - 1 ? combats[currentIdx + 1].id : null;
const settings = game.settings.get("core", Combat.CONFIG_SETTING); const settings = game.settings.get('core', Combat.CONFIG_SETTING);
// Prepare rendering data // Prepare rendering data
context = foundry.utils.mergeObject(context, { context = foundry.utils.mergeObject(context, {
@ -121,17 +121,18 @@ export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.
linked: combat?.scene !== null, linked: combat?.scene !== null,
labels: {} labels: {}
}); });
context.labels.scope = game.i18n.localize(`COMBAT.${context.linked ? "Linked" : "Unlinked"}`); context.labels.scope = game.i18n.localize(`COMBAT.${context.linked ? 'Linked' : 'Unlinked'}`);
if ( !hasCombat ) return context; if (!hasCombat) return context;
// Format information about each combatant in the encounter // Format information about each combatant in the encounter
let hasDecimals = false; let hasDecimals = false;
const turns = []; const turns = [];
for ( let [i, combatant] of combat.turns.entries() ) { for (let [i, combatant] of combat.turns.entries()) {
if ( !combatant.visible ) continue; if (!combatant.visible) continue;
// Prepare turn data // Prepare turn data
const resource = combatant.permission >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER ? combatant.resource : null; const resource =
combatant.permission >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER ? combatant.resource : null;
const turn = { const turn = {
id: combatant.id, id: combatant.id,
name: combatant.name, name: combatant.name,
@ -144,27 +145,25 @@ export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.
hasRolled: combatant.initiative !== null, hasRolled: combatant.initiative !== null,
hasResource: resource !== null, hasResource: resource !== null,
resource: resource, resource: resource,
canPing: (combatant.sceneId === canvas.scene?.id) && game.user.hasPermission("PING_CANVAS"), canPing: combatant.sceneId === canvas.scene?.id && game.user.hasPermission('PING_CANVAS'),
playerCharacter: game.user?.character?.id === combatant.actor.id, playerCharacter: game.user?.character?.id === combatant.actor.id,
ownedByPlayer: combatant.hasPlayerOwner, ownedByPlayer: combatant.hasPlayerOwner
}; };
if ( (turn.initiative !== null) && !Number.isInteger(turn.initiative) ) hasDecimals = true; if (turn.initiative !== null && !Number.isInteger(turn.initiative)) hasDecimals = true;
turn.css = [ turn.css = [turn.active ? 'active' : '', turn.hidden ? 'hidden' : '', turn.defeated ? 'defeated' : '']
turn.active ? "active" : "", .join(' ')
turn.hidden ? "hidden" : "", .trim();
turn.defeated ? "defeated" : ""
].join(" ").trim();
// Actor and Token status effects // Actor and Token status effects
turn.effects = new Set(); turn.effects = new Set();
if ( combatant.token ) { if (combatant.token) {
combatant.token.effects.forEach(e => turn.effects.add(e)); combatant.token.effects.forEach(e => turn.effects.add(e));
if ( combatant.token.overlayEffect ) turn.effects.add(combatant.token.overlayEffect); if (combatant.token.overlayEffect) turn.effects.add(combatant.token.overlayEffect);
} }
if ( combatant.actor ) { if (combatant.actor) {
for ( const effect of combatant.actor.temporaryEffects ) { for (const effect of combatant.actor.temporaryEffects) {
if ( effect.statuses.has(CONFIG.specialStatusEffects.DEFEATED) ) turn.defeated = true; if (effect.statuses.has(CONFIG.specialStatusEffects.DEFEATED)) turn.defeated = true;
else if ( effect.icon ) turn.effects.add(effect.icon); else if (effect.icon) turn.effects.add(effect.icon);
} }
} }
turns.push(turn); turns.push(turn);
@ -173,7 +172,7 @@ export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.
// Format initiative numeric precision // Format initiative numeric precision
const precision = CONFIG.Combat.initiative.decimals; const precision = CONFIG.Combat.initiative.decimals;
turns.forEach(t => { turns.forEach(t => {
if ( t.initiative !== null ) t.initiative = t.initiative.toFixed(hasDecimals ? precision : 0); if (t.initiative !== null) t.initiative = t.initiative.toFixed(hasDecimals ? precision : 0);
}); });
const fear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear); const fear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear);
@ -184,15 +183,15 @@ export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.
turn: combat.turn, turn: combat.turn,
turns: turns, turns: turns,
control: combat.combatant?.players?.includes(game.user), control: combat.combatant?.players?.includes(game.user),
fear: fear, fear: fear
}); });
} }
onFearUpdate = async () => { onFearUpdate = async () => {
this.render(true); this.render(true);
} };
async close(options){ async close(options) {
Hooks.off(socketEvent.DhpFearUpdate, this.onFearUpdate); Hooks.off(socketEvent.DhpFearUpdate, this.onFearUpdate);
return super.close(options); return super.close(options);

View file

@ -1,4 +1,4 @@
import { GMUpdateEvent, socketEvent } from "../helpers/socket.mjs"; import { GMUpdateEvent, socketEvent } from '../helpers/socket.mjs';
export default class DhpPlayers extends foundry.applications.ui.Players { export default class DhpPlayers extends foundry.applications.ui.Players {
constructor(data, context) { constructor(data, context) {
@ -7,11 +7,11 @@ export default class DhpPlayers extends foundry.applications.ui.Players {
Hooks.on(socketEvent.DhpFearUpdate, this.onFearUpdate); Hooks.on(socketEvent.DhpFearUpdate, this.onFearUpdate);
} }
get template(){ get template() {
return 'systems/daggerheart/templates/ui/players.hbs'; return 'systems/daggerheart/templates/ui/players.hbs';
} }
async getData(options={}) { async getData(options = {}) {
const context = super.getData(options); const context = super.getData(options);
context.fear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear); context.fear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear);
context.user = game.user; context.user = game.user;
@ -21,31 +21,31 @@ export default class DhpPlayers extends foundry.applications.ui.Players {
activateListeners(html) { activateListeners(html) {
// Toggle online/offline // Toggle online/offline
html.find(".players-mode").click(this._onToggleOfflinePlayers.bind(this)); html.find('.players-mode').click(this._onToggleOfflinePlayers.bind(this));
html.find(".fear-control.up").click(async event => await this.updateFear(event, 1)); html.find('.fear-control.up').click(async event => await this.updateFear(event, 1));
html.find(".fear-control.down").click(async event => await this.updateFear(event, -1)); html.find('.fear-control.down').click(async event => await this.updateFear(event, -1));
// Context menu // Context menu
const contextOptions = this._getUserContextOptions(); const contextOptions = this._getUserContextOptions();
Hooks.call("getUserContextOptions", html, contextOptions); Hooks.call('getUserContextOptions', html, contextOptions);
new ContextMenu(html, ".player", contextOptions); new ContextMenu(html, '.player', contextOptions);
} }
async updateFear(_, change){ async updateFear(_, change) {
const fear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear); const fear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear);
const value = Math.max(Math.min(fear+change, 6), 0); const value = Math.max(Math.min(fear + change, 6), 0);
Hooks.callAll(socketEvent.GMUpdate,GMUpdateEvent.UpdateFear, null, value); Hooks.callAll(socketEvent.GMUpdate, GMUpdateEvent.UpdateFear, null, value);
await game.socket.emit(`system.${SYSTEM.id}`, { await game.socket.emit(`system.${SYSTEM.id}`, {
action: socketEvent.GMUpdate, action: socketEvent.GMUpdate,
data: { action: GMUpdateEvent.UpdateFear, update: value }, data: { action: GMUpdateEvent.UpdateFear, update: value }
}); });
} }
onFearUpdate = async () => { onFearUpdate = async () => {
this.render(true); this.render(true);
} };
async close(options){ async close(options) {
Hooks.off(socketEvent.DhpFearUpdate, this.onFearUpdate); Hooks.off(socketEvent.DhpFearUpdate, this.onFearUpdate);
return super.close(options); return super.close(options);

View file

@ -1,7 +1,7 @@
export default class DhpRuler extends foundry.canvas.interaction.Ruler { export default class DhpRuler extends foundry.canvas.interaction.Ruler {
_getSegmentLabel(segment, totalDistance) { _getSegmentLabel(segment, totalDistance) {
const range = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.RangeMeasurement); const range = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.RangeMeasurement);
if(!range.enabled) return super._getSegmentLabel(segment, totalDistance); if (!range.enabled) return super._getSegmentLabel(segment, totalDistance);
const segmentDistance = Math.round(segment.distance * 100) / 100; const segmentDistance = Math.round(segment.distance * 100) / 100;
const totalDistanceValue = Math.round(totalDistance * 100) / 100; const totalDistanceValue = Math.round(totalDistance * 100) / 100;
@ -9,21 +9,21 @@ export default class DhpRuler extends foundry.canvas.interaction.Ruler {
return `${this.#getRangeLabel(segmentDistance, range)} [${this.#getRangeLabel(totalDistanceValue, range)}]`; return `${this.#getRangeLabel(segmentDistance, range)} [${this.#getRangeLabel(totalDistanceValue, range)}]`;
} }
#getRangeLabel(distance, settings){ #getRangeLabel(distance, settings) {
if(distance <= settings.melee){ if (distance <= settings.melee) {
return game.i18n.localize("DAGGERHEART.Range.Melee.Name"); return game.i18n.localize('DAGGERHEART.Range.Melee.Name');
} }
if(distance <= settings.veryClose){ if (distance <= settings.veryClose) {
return game.i18n.localize("DAGGERHEART.Range.VeryClose.Name"); return game.i18n.localize('DAGGERHEART.Range.VeryClose.Name');
} }
if(distance <= settings.close){ if (distance <= settings.close) {
return game.i18n.localize("DAGGERHEART.Range.Close.Name"); return game.i18n.localize('DAGGERHEART.Range.Close.Name');
} }
if(distance <= settings.far){ if (distance <= settings.far) {
return game.i18n.localize("DAGGERHEART.Range.Far.Name"); return game.i18n.localize('DAGGERHEART.Range.Far.Name');
} }
if(distance <= settings.veryFar){ if (distance <= settings.veryFar) {
return game.i18n.localize("DAGGERHEART.Range.VeryFar.Name"); return game.i18n.localize('DAGGERHEART.Range.VeryFar.Name');
} }
} }
} }

1278
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,13 @@
"@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-node-resolve": "^15.2.3",
"concurrently": "^8.2.2", "concurrently": "^8.2.2",
"husky": "^9.1.5",
"lint-staged": "^15.2.10",
"postcss": "^8.4.32", "postcss": "^8.4.32",
"prettier": "^3.5.3",
"rollup-plugin-postcss": "^4.0.2" "rollup-plugin-postcss": "^4.0.2"
},
"lint-staged": {
"**/*": "prettier --write --ignore-unknown"
} }
} }

View file

@ -1,6 +1,6 @@
/** @type {import('postcss-load-config').Config} */ /** @type {import('postcss-load-config').Config} */
const config = { const config = {
plugins: [] plugins: []
} };
module.exports = config module.exports = config;

View file

@ -7,7 +7,7 @@ export default {
output: { output: {
file: 'build/daggerheart.js', file: 'build/daggerheart.js',
format: 'cjs', format: 'cjs',
sourcemap: true, sourcemap: true
}, },
plugins: [ plugins: [
postcss({ postcss({
@ -22,8 +22,8 @@ export default {
}), }),
commonjs({ commonjs({
include: /node_modules/, include: /node_modules/,
requireReturnsDefault: 'auto', requireReturnsDefault: 'auto'
}), }),
resolve() resolve()
], ]
} };

View file

@ -4,10 +4,7 @@
"_id": "yKicceU4LesCgKwF", "_id": "yKicceU4LesCgKwF",
"img": "systems/daggerheart/assets/icons/classes/bard.png", "img": "systems/daggerheart/assets/icons/classes/bard.png",
"system": { "system": {
"domains": [ "domains": ["grace", "codex"],
"grace",
"codex"
],
"classItems": [], "classItems": [],
"damageThresholds": { "damageThresholds": {
"minor": 0, "minor": 0,
@ -67,16 +64,8 @@
"color": "", "color": "",
"attitude": "" "attitude": ""
}, },
"backgroundQuestions": [ "backgroundQuestions": ["", "", ""],
"", "connections": ["", "", ""]
"",
""
],
"connections": [
"",
"",
""
]
}, },
"multiclass": null, "multiclass": null,
"description": "" "description": ""

View file

@ -33,16 +33,8 @@
"suggestedSecondaryWeapon": null, "suggestedSecondaryWeapon": null,
"suggestedArmor": null, "suggestedArmor": null,
"characterDescription": {}, "characterDescription": {},
"backgroundQuestions": [ "backgroundQuestions": ["", "", ""],
"", "connections": ["", "", ""]
"",
""
],
"connections": [
"",
"",
""
]
}, },
"multiclass": null, "multiclass": null,
"description": "" "description": ""

View file

@ -33,16 +33,8 @@
"suggestedSecondaryWeapon": null, "suggestedSecondaryWeapon": null,
"suggestedArmor": null, "suggestedArmor": null,
"characterDescription": {}, "characterDescription": {},
"backgroundQuestions": [ "backgroundQuestions": ["", "", ""],
"", "connections": ["", "", ""]
"",
""
],
"connections": [
"",
"",
""
]
}, },
"multiclass": null, "multiclass": null,
"description": "" "description": ""

View file

@ -33,16 +33,8 @@
"suggestedSecondaryWeapon": null, "suggestedSecondaryWeapon": null,
"suggestedArmor": null, "suggestedArmor": null,
"characterDescription": {}, "characterDescription": {},
"backgroundQuestions": [ "backgroundQuestions": ["", "", ""],
"", "connections": ["", "", ""]
"",
""
],
"connections": [
"",
"",
""
]
}, },
"multiclass": null, "multiclass": null,
"description": "" "description": ""

View file

@ -33,16 +33,8 @@
"suggestedSecondaryWeapon": null, "suggestedSecondaryWeapon": null,
"suggestedArmor": null, "suggestedArmor": null,
"characterDescription": {}, "characterDescription": {},
"backgroundQuestions": [ "backgroundQuestions": ["", "", ""],
"", "connections": ["", "", ""]
"",
""
],
"connections": [
"",
"",
""
]
}, },
"multiclass": null, "multiclass": null,
"description": "" "description": ""

View file

@ -33,16 +33,8 @@
"suggestedSecondaryWeapon": null, "suggestedSecondaryWeapon": null,
"suggestedArmor": null, "suggestedArmor": null,
"characterDescription": {}, "characterDescription": {},
"backgroundQuestions": [ "backgroundQuestions": ["", "", ""],
"", "connections": ["", "", ""]
"",
""
],
"connections": [
"",
"",
""
]
}, },
"multiclass": null, "multiclass": null,
"description": "" "description": ""

View file

@ -33,16 +33,8 @@
"suggestedSecondaryWeapon": null, "suggestedSecondaryWeapon": null,
"suggestedArmor": null, "suggestedArmor": null,
"characterDescription": {}, "characterDescription": {},
"backgroundQuestions": [ "backgroundQuestions": ["", "", ""],
"", "connections": ["", "", ""]
"",
""
],
"connections": [
"",
"",
""
]
}, },
"multiclass": null, "multiclass": null,
"description": "" "description": ""

View file

@ -33,16 +33,8 @@
"suggestedSecondaryWeapon": null, "suggestedSecondaryWeapon": null,
"suggestedArmor": null, "suggestedArmor": null,
"characterDescription": {}, "characterDescription": {},
"backgroundQuestions": [ "backgroundQuestions": ["", "", ""],
"", "connections": ["", "", ""]
"",
""
],
"connections": [
"",
"",
""
]
}, },
"multiclass": null, "multiclass": null,
"description": "" "description": ""

View file

@ -33,16 +33,8 @@
"suggestedSecondaryWeapon": null, "suggestedSecondaryWeapon": null,
"suggestedArmor": null, "suggestedArmor": null,
"characterDescription": {}, "characterDescription": {},
"backgroundQuestions": [ "backgroundQuestions": ["", "", ""],
"", "connections": ["", "", ""]
"",
""
],
"connections": [
"",
"",
""
]
}, },
"multiclass": null, "multiclass": null,
"description": "" "description": ""

View file

@ -33,16 +33,8 @@
"suggestedSecondaryWeapon": null, "suggestedSecondaryWeapon": null,
"suggestedArmor": null, "suggestedArmor": null,
"characterDescription": {}, "characterDescription": {},
"backgroundQuestions": [ "backgroundQuestions": ["", "", ""],
"", "connections": ["", "", ""]
"",
""
],
"connections": [
"",
"",
""
]
}, },
"multiclass": null, "multiclass": null,
"description": "" "description": ""

View file

@ -33,16 +33,8 @@
"suggestedSecondaryWeapon": null, "suggestedSecondaryWeapon": null,
"suggestedArmor": null, "suggestedArmor": null,
"characterDescription": {}, "characterDescription": {},
"backgroundQuestions": [ "backgroundQuestions": ["", "", ""],
"", "connections": ["", "", ""]
"",
""
],
"connections": [
"",
"",
""
]
}, },
"multiclass": null, "multiclass": null,
"description": "" "description": ""

View file

@ -1,12 +1,15 @@
form.daggerheart.views.downtime { // Shouldn't be needed, but DEFAULT_OPTIONS doesn't accept Height: 'auto' form.daggerheart.views.downtime {
// Shouldn't be needed, but DEFAULT_OPTIONS doesn't accept Height: 'auto'
height: auto !important; height: auto !important;
} }
div.daggerheart.views.death-move { // Shouldn't be needed, but DEFAULT_OPTIONS doesn't accept Height: 'auto' div.daggerheart.views.death-move {
// Shouldn't be needed, but DEFAULT_OPTIONS doesn't accept Height: 'auto'
height: auto !important; height: auto !important;
} }
div.daggerheart.views.multiclass { // Shouldn't be needed, but DEFAULT_OPTIONS doesn't accept Height: 'auto' div.daggerheart.views.multiclass {
// Shouldn't be needed, but DEFAULT_OPTIONS doesn't accept Height: 'auto'
height: auto !important; height: auto !important;
} }
@ -153,7 +156,8 @@ div.daggerheart.views.multiclass { // Shouldn't be needed, but DEFAULT_OPTIONS d
margin-right: 8px; margin-right: 8px;
cursor: pointer; cursor: pointer;
&:hover, &.selected { &:hover,
&.selected {
filter: drop-shadow(0 0 6px gold); filter: drop-shadow(0 0 6px gold);
} }
} }
@ -199,7 +203,8 @@ div.daggerheart.views.multiclass { // Shouldn't be needed, but DEFAULT_OPTIONS d
} }
.roll-dialog-container { .roll-dialog-container {
.disadvantage, .advantage { .disadvantage,
.advantage {
border: 2px solid @secondaryAccent; border: 2px solid @secondaryAccent;
border-radius: 6px; border-radius: 6px;
display: flex; display: flex;
@ -297,7 +302,7 @@ div.daggerheart.views.multiclass { // Shouldn't be needed, but DEFAULT_OPTIONS d
align-items: center; align-items: center;
flex: 1; flex: 1;
.dice-inner-container{ .dice-inner-container {
position: relative; position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
@ -391,11 +396,13 @@ div.daggerheart.views.multiclass { // Shouldn't be needed, but DEFAULT_OPTIONS d
font-size: 24px; font-size: 24px;
cursor: pointer; cursor: pointer;
&.selected:not(.disabled), &:hover:not(.disabled) { &.selected:not(.disabled),
&:hover:not(.disabled) {
filter: drop-shadow(0 0 3px gold); filter: drop-shadow(0 0 3px gold);
} }
&.inactive, &.disabled { &.inactive,
&.disabled {
cursor: initial; cursor: initial;
opacity: 0.4; opacity: 0.4;
} }

View file

@ -199,7 +199,7 @@
border-color: black; border-color: black;
flex-basis: calc(50% - 2px); flex-basis: calc(50% - 2px);
&:nth-of-type(n+3){ &:nth-of-type(n + 3) {
margin-top: @tinyMargin; margin-top: @tinyMargin;
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,14 @@
@import "./variables/variables.less"; @import './variables/variables.less';
@import "./class.less"; @import './class.less';
@import "./pc.less"; @import './pc.less';
@import "./ui.less"; @import './ui.less';
@import "./chat.less"; @import './chat.less';
@import "./item.less"; @import './item.less';
@import "./application.less"; @import './application.less';
@import "./sheets//sheets.less"; @import './sheets//sheets.less';
@import "./components.less"; @import './components.less';
@import "./dialog.less"; @import './dialog.less';
@import "../node_modules/@yaireo/tagify/dist/tagify.css"; @import '../node_modules/@yaireo/tagify/dist/tagify.css';
#logo { #logo {
content: url(../assets/DaggerheartLogo.webp); content: url(../assets/DaggerheartLogo.webp);
@ -52,7 +52,7 @@
} }
/****/ /****/
img[data-edit="img"] { img[data-edit='img'] {
min-width: 64px; min-width: 64px;
min-height: 64px; min-height: 64px;
} }
@ -84,8 +84,7 @@
opacity: 0.6; opacity: 0.6;
} }
&:hover:not(.disabled) {
&:hover:not(.disabled){
cursor: pointer; cursor: pointer;
filter: drop-shadow(0 0 3px @mainShadow); filter: drop-shadow(0 0 3px @mainShadow);

View file

@ -53,7 +53,7 @@
font-weight: bold; font-weight: bold;
} }
input[type="checkbox"] { input[type='checkbox'] {
margin: 0; margin: 0;
} }
} }

View file

@ -118,7 +118,7 @@
} }
} }
.level-container{ .level-container {
position: relative; position: relative;
bottom: 4px; bottom: 4px;
flex: none; flex: none;
@ -147,7 +147,8 @@
font-weight: bold; font-weight: bold;
font-size: 20px; font-size: 20px;
text-align: center; text-align: center;
&:not(:hover), &:not(:focus) { &:not(:hover),
&:not(:focus) {
border: none; border: none;
} }
} }
@ -177,7 +178,7 @@
font-size: 12px; font-size: 12px;
&.levelup { &.levelup {
color:gold; color: gold;
filter: drop-shadow(0px 0px 3px orange); filter: drop-shadow(0px 0px 3px orange);
font-weight: bold; font-weight: bold;
cursor: pointer; cursor: pointer;
@ -315,7 +316,8 @@
} }
} }
& i.selected, &:hover i.selected { & i.selected,
&:hover i.selected {
color: green; color: green;
opacity: 1; opacity: 1;
} }
@ -411,7 +413,8 @@
font-weight: bold; font-weight: bold;
font-size: 30px; font-size: 30px;
text-align: center; text-align: center;
&:not(:hover), &:not(:focus) { &:not(:hover),
&:not(:focus) {
border: none; border: none;
} }
} }
@ -606,7 +609,7 @@
.disabled-experience { .disabled-experience {
border: @thinBorder solid @borderTertiary; border: @thinBorder solid @borderTertiary;
background: rgba(0, 0, 0, 0.20); background: rgba(0, 0, 0, 0.2);
} }
} }
.gold-section { .gold-section {
@ -644,7 +647,8 @@
gap: @tinyMargin; gap: @tinyMargin;
} }
.gold-row, .gold-column { .gold-row,
.gold-column {
img { img {
min-width: 14px; min-width: 14px;
min-height: 14px; min-height: 14px;
@ -654,7 +658,8 @@
&:hover { &:hover {
cursor: pointer; cursor: pointer;
filter: invert(0%) sepia(100%) saturate(0%) hue-rotate(21deg) brightness(17%) contrast(103%) drop-shadow(0 0 3px @mainShadow); filter: invert(0%) sepia(100%) saturate(0%) hue-rotate(21deg) brightness(17%)
contrast(103%) drop-shadow(0 0 3px @mainShadow);
} }
} }
@ -663,7 +668,8 @@
filter: drop-shadow(0 0 3px @mainShadow); filter: drop-shadow(0 0 3px @mainShadow);
} }
img:not(.owned), i:not(.owned) { img:not(.owned),
i:not(.owned) {
opacity: 0.4; opacity: 0.4;
} }
} }
@ -729,7 +735,7 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
&:hover:not(.disabled):not(.used){ &:hover:not(.disabled):not(.used) {
cursor: pointer; cursor: pointer;
filter: drop-shadow(0 0 3px @mainShadow); filter: drop-shadow(0 0 3px @mainShadow);
} }
@ -752,7 +758,7 @@
&.used::after { &.used::after {
position: absolute; position: absolute;
content: "/"; content: '/';
color: @borderTertiary; color: @borderTertiary;
font-weight: 700; font-weight: 700;
font-size: 1.7em; font-size: 1.7em;
@ -816,7 +822,7 @@
color: black; color: black;
} }
&:not(:last-of-type){ &:not(:last-of-type) {
margin-right: @tinyMargin; margin-right: @tinyMargin;
} }
} }
@ -925,7 +931,8 @@
} }
} }
.inventory-armor-section, .inventory-weapon-section { .inventory-armor-section,
.inventory-weapon-section {
width: 100%; width: 100%;
margin-bottom: @fullMargin; margin-bottom: @fullMargin;
text-transform: uppercase; text-transform: uppercase;
@ -948,7 +955,7 @@
align-items: center; align-items: center;
i { i {
&:hover:not(.disabled){ &:hover:not(.disabled) {
cursor: pointer; cursor: pointer;
filter: drop-shadow(0px 0px 3px red); filter: drop-shadow(0px 0px 3px red);
} }
@ -1213,7 +1220,7 @@
bottom: -9px; bottom: -9px;
z-index: 1; z-index: 1;
.abilities-card-type-text{ .abilities-card-type-text {
padding: 0px 4px; padding: 0px 4px;
border: 1px solid black; border: 1px solid black;
border-radius: 6px; border-radius: 6px;
@ -1291,7 +1298,7 @@
} }
} }
&:hover .abilities-card-menu{ &:hover .abilities-card-menu {
height: 40px; height: 40px;
left: 0px; left: 0px;
} }
@ -1389,7 +1396,7 @@
overflow: auto; overflow: auto;
.inventory-item-list { .inventory-item-list {
list-style-type:none; list-style-type: none;
padding: 0 @largePadding; padding: 0 @largePadding;
margin-top: 0; margin-top: 0;

View file

@ -66,7 +66,7 @@
cursor: pointer; cursor: pointer;
&:hover { &:hover {
filter: drop-shadow(0 0 3px red), filter: drop-shadow(0 0 3px red);
} }
} }
} }
@ -161,7 +161,7 @@
cursor: pointer; cursor: pointer;
&:hover { &:hover {
filter: drop-shadow(0 0 3px red), filter: drop-shadow(0 0 3px red);
} }
} }
} }
@ -219,7 +219,7 @@
.moves-name { .moves-name {
font-weight: bold; font-weight: bold;
text-decoration: none;; text-decoration: none;
} }
.move-description { .move-description {
@ -230,13 +230,12 @@
} }
.moves-edit-container { .moves-edit-container {
i { i {
margin-left: 4px; margin-left: 4px;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
filter: drop-shadow(0 0 3px red), filter: drop-shadow(0 0 3px red);
} }
} }
} }

View file

@ -2,5 +2,4 @@
.editor { .editor {
height: 200px; height: 200px;
} }
} }

View file

@ -1,6 +1,6 @@
@import "./heritage.less"; @import './heritage.less';
@import "./class.less"; @import './class.less';
@import "./adversary.less"; @import './adversary.less';
.daggerheart.sheet { .daggerheart.sheet {
.title-container { .title-container {
@ -117,7 +117,7 @@
position: relative; position: relative;
width: calc(100% - 2px); width: calc(100% - 2px);
background: rgba(0, 0, 0, 0.05); background: rgba(0, 0, 0, 0.05);
height: var(--form-field-height);; height: var(--form-field-height);
display: flex; display: flex;
border: 1px solid rgb(122, 121, 113); border: 1px solid rgb(122, 121, 113);
border-radius: 3px; border-radius: 3px;
@ -179,7 +179,6 @@
border: 0; border: 0;
i { i {
} }
} }
} }

View file

@ -63,8 +63,7 @@
opacity: 0.6; opacity: 0.6;
} }
&:hover:not(.disabled) {
&:hover:not(.disabled){
cursor: pointer; cursor: pointer;
filter: drop-shadow(0 0 3px @mainShadow); filter: drop-shadow(0 0 3px @mainShadow);
} }

View file

@ -1,2 +1,2 @@
@import "./colors.less"; @import './colors.less';
@import "./values.less"; @import './values.less';

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