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
#### For Foundry VTT
This is a repo for a Foundry VTT implementation of daggerheart. It is not associated with critical role
or darrington press.
# Table Of Contents
- [Overview](#overview)
- [Developer Guide](#developer-guide)
# Overview
# 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
- 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: Linux link can be made using `ln -snf <path to development folder> daggerheart` inside the system folder
- Install npm `npm install`
- 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-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>`
- The main is likely in `<Foundry Install Location>/resouces/app/main.js`
- 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`
[Foundry VTT Website][1]
[1]: https://foundryvtt.com/

View file

@ -17,10 +17,13 @@ Hooks.once('init', () => {
game.system.api = {
applications,
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.dataModels = {
@ -33,45 +36,45 @@ Hooks.once('init', () => {
miscellaneous: models.DhpMiscellaneous,
consumable: models.DhpConsumable,
weapon: models.DhpWeapon,
armor: models.DhpArmor,
armor: models.DhpArmor
};
const { Items, Actors } = foundry.documents.collections;
Items.unregisterSheet("core", foundry.appv1.sheets.ItemSheet);
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.DhpClassSheet, {types: ["class"], 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.DhpDomainCardSheet, {types: ["domainCard"], 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.DhpWeapon, {types: ["weapon"], makeDefault: true});
Items.registerSheet(SYSTEM.id, applications.DhpArmor, {types: ["armor"], makeDefault: true});
Items.unregisterSheet('core', foundry.appv1.sheets.ItemSheet);
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.DhpClassSheet, { types: ['class'], 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.DhpDomainCardSheet, { types: ['domainCard'], 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.DhpWeapon, { types: ['weapon'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.DhpArmor, { types: ['armor'], makeDefault: true });
CONFIG.Actor.documentClass = documents.DhpActor;
CONFIG.Actor.dataModels = {
pc: models.DhpPC,
adversary: models.DhpAdversary,
environment: models.DhpEnvironment,
environment: models.DhpEnvironment
};
Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet);
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.DhpEnvironment, {types: ["environment"], makeDefault: true});
Actors.unregisterSheet('core', foundry.appv1.sheets.ActorSheet);
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.DhpEnvironment, { types: ['environment'], makeDefault: true });
CONFIG.Combat.dataModels = {
base: models.DhpCombat,
base: models.DhpCombat
};
CONFIG.Combatant.dataModels = {
base: models.DhpCombatant,
base: models.DhpCombatant
};
CONFIG.ChatMessage.dataModels ={
CONFIG.ChatMessage.dataModels = {
dualityRoll: models.DhpDualityRoll,
adversaryRoll: models.DhpAdversaryRoll,
abilityUse: models.DhpAbilityUse,
abilityUse: models.DhpAbilityUse
};
CONFIG.ChatMessage.documentClass = applications.DhpChatMessage;
@ -90,22 +93,24 @@ Hooks.once('init', () => {
return preloadHandlebarsTemplates();
});
Hooks.once('dicesoniceready', () => {
});
Hooks.once('dicesoniceready', () => {});
Hooks.on(socketEvent.GMUpdate, async (action, uuid, update) => {
if(game.user.isGM){
if (game.user.isGM) {
const document = uuid ? await fromUuid(uuid) : null;
switch(action){
switch (action) {
case GMUpdateEvent.UpdateDocument:
if(document && update){
if (document && update) {
await document.update(update);
}
break;
case GMUpdateEvent.UpdateFear:
if(game.user.isGM){
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear, Math.max(Math.min(update, 6), 0));
if (game.user.isGM) {
await game.settings.set(
SYSTEM.id,
SYSTEM.SETTINGS.gameSettings.Resources.Fear,
Math.max(Math.min(update, 6), 0)
);
Hooks.callAll(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([
"systems/daggerheart/templates/sheets/parts/attributes.hbs",
"systems/daggerheart/templates/sheets/parts/defense.hbs",
"systems/daggerheart/templates/sheets/parts/armor.hbs",
"systems/daggerheart/templates/sheets/parts/experience.hbs",
"systems/daggerheart/templates/sheets/parts/features.hbs",
"systems/daggerheart/templates/sheets/parts/gold.hbs",
"systems/daggerheart/templates/sheets/parts/health.hbs",
"systems/daggerheart/templates/sheets/parts/hope.hbs",
"systems/daggerheart/templates/sheets/parts/inventory.hbs",
"systems/daggerheart/templates/sheets/parts/weapons.hbs",
"systems/daggerheart/templates/sheets/parts/domainCard.hbs",
"systems/daggerheart/templates/sheets/parts/heritage.hbs",
"systems/daggerheart/templates/sheets/parts/subclassFeature.hbs",
"systems/daggerheart/templates/sheets/parts/effects.hbs",
"systems/daggerheart/templates/sheets/pc/sections/inventory.hbs",
"systems/daggerheart/templates/sheets/pc/sections/loadout.hbs",
"systems/daggerheart/templates/sheets/pc/parts/heritageCard.hbs",
"systems/daggerheart/templates/sheets/pc/parts/advancementCard.hbs",
"systems/daggerheart/templates/views/parts/level.hbs",
"systems/daggerheart/templates/components/slider.hbs",
'systems/daggerheart/templates/sheets/parts/attributes.hbs',
'systems/daggerheart/templates/sheets/parts/defense.hbs',
'systems/daggerheart/templates/sheets/parts/armor.hbs',
'systems/daggerheart/templates/sheets/parts/experience.hbs',
'systems/daggerheart/templates/sheets/parts/features.hbs',
'systems/daggerheart/templates/sheets/parts/gold.hbs',
'systems/daggerheart/templates/sheets/parts/health.hbs',
'systems/daggerheart/templates/sheets/parts/hope.hbs',
'systems/daggerheart/templates/sheets/parts/inventory.hbs',
'systems/daggerheart/templates/sheets/parts/weapons.hbs',
'systems/daggerheart/templates/sheets/parts/domainCard.hbs',
'systems/daggerheart/templates/sheets/parts/heritage.hbs',
'systems/daggerheart/templates/sheets/parts/subclassFeature.hbs',
'systems/daggerheart/templates/sheets/parts/effects.hbs',
'systems/daggerheart/templates/sheets/pc/sections/inventory.hbs',
'systems/daggerheart/templates/sheets/pc/sections/loadout.hbs',
'systems/daggerheart/templates/sheets/pc/parts/heritageCard.hbs',
'systems/daggerheart/templates/sheets/pc/parts/advancementCard.hbs',
'systems/daggerheart/templates/views/parts/level.hbs',
'systems/daggerheart/templates/components/slider.hbs'
]);
};
};

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
export default class DhpChatMesssage extends ChatMessage {
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);
}

View file

@ -1,8 +1,8 @@
import DaggerheartSheet from '../sheets/daggerheart-sheet.mjs';
const {ApplicationV2} = foundry.applications.api;
const { ApplicationV2 } = foundry.applications.api;
export default class DaggerheartActionConfig extends DaggerheartSheet(ApplicationV2) {
constructor(action){
constructor(action) {
super({});
this.action = action;
@ -15,35 +15,42 @@ export default class DaggerheartActionConfig extends DaggerheartSheet(Applicatio
static DEFAULT_OPTIONS = {
tag: 'form',
id: "daggerheart-action",
classes: ["daggerheart", "views", "action"],
id: 'daggerheart-action',
classes: ['daggerheart', 'views', 'action'],
position: { width: 600, height: 'auto' },
actions: {
toggleSection: this.toggleSection,
toggleSection: this.toggleSection
},
form: {
handler: this.updateForm,
closeOnSubmit: true,
},
closeOnSubmit: true
}
};
static PARTS = {
form: {
id: "action",
template: "systems/daggerheart/templates/views/action.hbs"
}
id: 'action',
template: 'systems/daggerheart/templates/views/action.hbs'
}
};
_getTabs() {
const tabs = {
effects: { active: true, cssClass: '', group: 'primary', id: 'effects', icon: null, label: 'Effects' },
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.cssClass = v.active ? "active" : "";
v.cssClass = v.active ? 'active' : '';
}
return tabs;
@ -65,10 +72,10 @@ export default class DaggerheartActionConfig extends DaggerheartSheet(Applicatio
static async updateForm(event, _, formData) {
const data = foundry.utils.expandObject(foundry.utils.mergeObject(this.action.toObject(), formData.object));
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);
}
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) {
return class DhpSheet extends Base {
static applicationType = "sheets";
static documentType = "";
static applicationType = 'sheets';
static documentType = '';
static get 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`,
height: "auto",
height: 'auto',
submitOnChange: true,
submitOnClose: false,
width: 450
@ -16,7 +16,7 @@ export default function DhpApplicationMixin(Base) {
/** @override */
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 = documentName;
return `[${typeLabel}] ${name}`;
@ -32,7 +32,7 @@ export default function DhpApplicationMixin(Base) {
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) {
@ -44,5 +44,5 @@ export default function DhpApplicationMixin(Base) {
}
async _handleAction(action, event, button) {}
}
};
}

View file

@ -1,53 +1,52 @@
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
export default class DamageSelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(rollString, bonusDamage, hope, resolve){
constructor(rollString, bonusDamage, hope, resolve) {
super({});
this.data = {
rollString,
bonusDamage: bonusDamage.reduce((acc, x) => {
if(x.appliesOn === SYSTEM.EFFECTS.applyLocations.damageRoll.id){
acc.push(({
if (x.appliesOn === SYSTEM.EFFECTS.applyLocations.damageRoll.id) {
acc.push({
...x,
hopeUses: 0
}));
});
}
return acc;
}, []),
hope,
}
hope
};
this.resolve = resolve;
}
static DEFAULT_OPTIONS = {
tag: 'form',
classes: ["daggerheart", "views", "damage-selection"],
classes: ['daggerheart', 'views', 'damage-selection'],
position: {
width: 400,
height: "auto"
height: 'auto'
},
actions: {
decreaseHopeUse: this.decreaseHopeUse,
increaseHopeUse: this.increaseHopeUse,
rollDamage: this.rollDamage,
rollDamage: this.rollDamage
},
form: {
handler: this.updateSelection,
submitOnChange: true,
closeOnSubmit: false,
closeOnSubmit: false
}
};
/** @override */
static PARTS = {
damageSelection: {
id: "damageSelection",
template: "systems/daggerheart/templates/views/damageSelection.hbs"
}
id: 'damageSelection',
template: 'systems/daggerheart/templates/views/damageSelection.hbs'
}
};
/* -------------------------------------------- */
@ -60,19 +59,19 @@ export default class DamageSelectionDialog extends HandlebarsApplicationMixin(Ap
return {
rollString: this.getRollString(),
bonusDamage: this.data.bonusDamage,
hope: this.data.hope+1,
hopeUsed: this.getHopeUsed(),
}
hope: this.data.hope + 1,
hopeUsed: this.getHopeUsed()
};
}
static updateSelection(event, _, formData){
static updateSelection(event, _, formData) {
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;
if(bonusDamage[index].hopeUses){
if (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);
}
getRollString(){
return this.data.rollString.concat(this.data.bonusDamage.reduce((acc, x) => {
if(x.initiallySelected){
const nr = 1+x.hopeUses;
getRollString() {
return this.data.rollString.concat(
this.data.bonusDamage.reduce((acc, x) => {
if (x.initiallySelected) {
const nr = 1 + x.hopeUses;
const baseDamage = x.value;
return acc.concat(` + ${nr}${baseDamage}`);
}
return acc;
}, ""));
}, '')
);
}
getHopeUsed(){
return this.data.bonusDamage.reduce((acc, x) => acc+x.hopeUses, 0);
getHopeUsed() {
return this.data.bonusDamage.reduce((acc, x) => acc + x.hopeUses, 0);
}
static decreaseHopeUse(_, button){
static decreaseHopeUse(_, button) {
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.render(true);
}
}
static increaseHopeUse(_, button){
static increaseHopeUse(_, button) {
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.render(true);
}
}
static rollDamage(){
this.resolve({ rollString: this.getRollString(), bonusDamage: this.data.bonusDamage, hopeUsed: this.getHopeUsed() });
static rollDamage() {
this.resolve({
rollString: this.getRollString(),
bonusDamage: this.data.bonusDamage,
hopeUsed: this.getHopeUsed()
});
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) {
constructor(actor){
constructor(actor) {
super({});
this.actor = actor;
this.selectedMove = null;
}
get title(){
return game.i18n.format("DAGGERHEART.Application.DeathMove.Title", { actor: this.actor.name });
get title() {
return game.i18n.format('DAGGERHEART.Application.DeathMove.Title', { actor: this.actor.name });
}
static DEFAULT_OPTIONS = {
classes: ["daggerheart", "views", "death-move"],
classes: ['daggerheart', 'views', 'death-move'],
position: { width: 800, height: 'auto' },
actions: {
selectMove: this.selectMove,
takeMove: this.takeMove,
},
takeMove: this.takeMove
}
};
static PARTS = {
application: {
id: "death-move",
template: "systems/daggerheart/templates/views/deathMove.hbs"
}
id: 'death-move',
template: 'systems/daggerheart/templates/views/deathMove.hbs'
}
};
async _prepareContext(_options) {
const context = await super._prepareContext(_options);
@ -36,24 +36,23 @@ export default class DhpDeathMove extends HandlebarsApplicationMixin(Application
return context;
}
static selectMove(_, button){
static selectMove(_, button) {
const move = button.dataset.move;
this.selectedMove = SYSTEM.GENERAL.deathMoves[move];
this.render();
}
static async takeMove(){
const cls = getDocumentClass("ChatMessage");
static async takeMove() {
const cls = getDocumentClass('ChatMessage');
const msg = new cls({
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,
title: game.i18n.localize(this.selectedMove.name),
img: this.selectedMove.img,
description: game.i18n.localize(this.selectedMove.description),
}),
description: game.i18n.localize(this.selectedMove.description)
})
});
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) {
constructor(actor, shortrest){
constructor(actor, shortrest) {
super({});
this.actor = actor;
@ -11,27 +11,27 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
this.customActivity = SYSTEM.GENERAL.downtime.custom;
}
get title(){
return `${this.actor.name} - ${this.shortrest ? 'Short Rest': 'Long Rest'}`;
get title() {
return `${this.actor.name} - ${this.shortrest ? 'Short Rest' : 'Long Rest'}`;
}
static DEFAULT_OPTIONS = {
tag: 'form',
classes: ["daggerheart", "views", "downtime"],
classes: ['daggerheart', 'views', 'downtime'],
position: { width: 800, height: 'auto' },
actions: {
selectActivity: this.selectActivity,
takeDowntime: this.takeDowntime,
takeDowntime: this.takeDowntime
},
form: { handler: this.updateData, submitOnChange: true }
};
static PARTS = {
application: {
id: "downtime",
template: "systems/daggerheart/templates/views/downtime.hbs"
}
id: 'downtime',
template: 'systems/daggerheart/templates/views/downtime.hbs'
}
};
async _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.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;
}
static selectActivity(_, button){
static selectActivity(_, button) {
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();
}
static async takeDowntime(){
const refreshedFeatures = this.shortrest ? this.actor.system.refreshableFeatures.shortRest : [...this.actor.system.refreshableFeatures.shortRest, ...this.actor.system.refreshableFeatures.longRest];
for(var feature of refreshedFeatures){
static async takeDowntime() {
const refreshedFeatures = this.shortrest
? this.actor.system.refreshableFeatures.shortRest
: [...this.actor.system.refreshableFeatures.shortRest, ...this.actor.system.refreshableFeatures.longRest];
for (var feature of refreshedFeatures) {
await feature.system.refresh();
}
const cls = getDocumentClass("ChatMessage");
const cls = getDocumentClass('ChatMessage');
const msg = new cls({
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,
title: game.i18n.localize(this.selectedActivity.name),
img: this.selectedActivity.img,
description: game.i18n.localize(this.selectedActivity.description),
refreshedFeatures: refreshedFeatures,
}),
refreshedFeatures: refreshedFeatures
})
});
cls.create(msg.toObject());
@ -75,7 +84,7 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
this.close();
}
static async updateData(event, element, formData){
static async updateData(event, element, formData) {
this.customActivity = foundry.utils.mergeObject(this.customActivity, formData.object);
this.render();
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -21,7 +21,6 @@
// return context;
// }
// async _handleAction(action, event, button) {
// switch(action){
// case 'attributeRoll':
@ -39,36 +38,36 @@ const { ItemSheetV2 } = foundry.applications.sheets;
export default class DomainCardSheet extends DaggerheartSheet(ItemSheetV2) {
static DEFAULT_OPTIONS = {
tag: 'form',
id: "daggerheart-domainCard",
classes: ["daggerheart", "sheet", "domain-card"],
id: 'daggerheart-domainCard',
classes: ['daggerheart', 'sheet', 'domain-card'],
position: { width: 600, height: 600 },
actions: {
addAction: this.addAction,
editAction: this.editAction,
removeAction: this.removeAction,
removeAction: this.removeAction
},
form: {
handler: this.updateForm,
submitOnChange: true,
closeOnSubmit: false,
},
closeOnSubmit: false
}
};
static PARTS = {
form: {
id: "feature",
template: "systems/daggerheart/templates/sheets/domainCard.hbs"
}
id: 'feature',
template: 'systems/daggerheart/templates/sheets/domainCard.hbs'
}
};
_getTabs() {
const tabs = {
general: { active: true, cssClass: '', group: 'primary', id: 'general', icon: null, label: 'General' },
actions: { active: false, cssClass: '', group: 'primary', id: 'actions', icon: null, label: 'Actions' },
}
for ( const v of Object.values(tabs) ) {
actions: { active: false, cssClass: '', group: 'primary', id: 'actions', icon: null, label: 'Actions' }
};
for (const v of Object.values(tabs)) {
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;
@ -83,28 +82,37 @@ export default class DomainCardSheet extends DaggerheartSheet(ItemSheetV2) {
}
static async updateForm(event, _, formData) {
await this.document.update(formData.object)
await this.document.update(formData.object);
this.render();
}
static async addAction(){
const actionIndexes = this.document.system.actions.map(x => x.id.split('-')[2]).sort((a, b) => a-b);
const action = await new DaggerheartAction({
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] });
await (new DaggerheartActionConfig(this.document.system.actions[this.document.system.actions.length-1])).render(true);
static async addAction() {
const actionIndexes = this.document.system.actions.map(x => x.id.split('-')[2]).sort((a, b) => a - b);
const action = await new DaggerheartAction(
{
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] });
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];
await (new DaggerheartActionConfig(action)).render(true);
await new DaggerheartActionConfig(action).render(true);
}
static async removeAction(event, button){
static async removeAction(event, button) {
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;
export default class DhpEnvironment extends DaggerheartSheet(DocumentSheetV2) {
constructor(options){
constructor(options) {
super(options);
this.editMode = false;
@ -11,10 +10,10 @@ export default class DhpEnvironment extends DaggerheartSheet(DocumentSheetV2) {
static DEFAULT_OPTIONS = {
tag: 'form',
classes: ["daggerheart", "sheet", "adversary", "environment"],
classes: ['daggerheart', 'sheet', 'adversary', 'environment'],
position: {
width: 600,
height: "auto"
height: 'auto'
},
actions: {
toggleSlider: this.toggleSlider,
@ -23,22 +22,22 @@ export default class DhpEnvironment extends DaggerheartSheet(DocumentSheetV2) {
removeFeature: this.removeFeature,
addTone: this.addTone,
removeTone: this.removeTone,
useFeature: this.useFeature,
useFeature: this.useFeature
},
form: {
handler: this._updateForm,
closeOnSubmit: false,
submitOnChange: true,
submitOnChange: true
}
};
/** @override */
static PARTS = {
form: {
id: "form",
template: "systems/daggerheart/templates/sheets/environment.hbs"
}
id: 'form',
template: 'systems/daggerheart/templates/sheets/environment.hbs'
}
};
/* -------------------------------------------- */
@ -56,7 +55,7 @@ export default class DhpEnvironment extends DaggerheartSheet(DocumentSheetV2) {
data: {
type: game.i18n.localize(SYSTEM.ACTOR.adversaryTypes[this.document.system.type].name),
features: this.document.items.reduce((acc, x) => {
if(x.type === 'feature'){
if (x.type === 'feature') {
const feature = x.toObject();
acc.push({
...feature,
@ -69,59 +68,65 @@ export default class DhpEnvironment extends DaggerheartSheet(DocumentSheetV2) {
}
return acc;
}, []),
}, [])
},
editMode: this.editMode,
config: SYSTEM,
}
config: SYSTEM
};
}
static async _updateForm(event, _, formData) {
await this.document.update(formData.object)
await this.document.update(formData.object);
this.render();
}
static toggleSlider(){
static toggleSlider() {
this.editMode = !this.editMode;
this.render();
}
static async viewFeature(_, button){
static async viewFeature(_, button) {
const move = await fromUuid(button.dataset.feature);
move.sheet.render(true);
}
static async addFeature(){
const result = await this.document.createEmbeddedDocuments("Item", [{
static async addFeature() {
const result = await this.document.createEmbeddedDocuments('Item', [
{
name: game.i18n.localize('DAGGERHEART.Sheets.Environment.NewFeature'),
type: 'feature',
}]);
type: 'feature'
}
]);
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();
}
static async addTone(){
await this.document.update({ "system.toneAndFeel": [...this.document.system.toneAndFeel, ''] });
static async addTone() {
await this.document.update({ 'system.toneAndFeel': [...this.document.system.toneAndFeel, ''] });
}
static async removeTone(button){
await this.document.update({ "system.toneAndFeel": this.document.system.toneAndFeel.filter((_, index) => index !== Number.parseInt(button.dataset.tone) )});
static async removeTone(button) {
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 cls = getDocumentClass("ChatMessage");
const cls = getDocumentClass('ChatMessage');
const msg = new cls({
user: game.user.id,
content: await renderTemplate("systems/daggerheart/templates/chat/ability-use.hbs", {
title: game.i18n.format("DAGGERHEART.Chat.EnvironmentTitle", { actionType: button.dataset.actionType }),
card: { name: item.name, img: item.img, description: item.system.description },
}),
content: await renderTemplate('systems/daggerheart/templates/chat/ability-use.hbs', {
title: game.i18n.format('DAGGERHEART.Chat.EnvironmentTitle', { actionType: button.dataset.actionType }),
card: { name: item.name, img: item.img, description: item.system.description }
})
});
cls.create(msg.toObject());

View file

@ -4,7 +4,7 @@ import DaggerheartSheet from './daggerheart-sheet.mjs';
const { ItemSheetV2 } = foundry.applications.sheets;
export default class FeatureSheet extends DaggerheartSheet(ItemSheetV2) {
constructor(options={}){
constructor(options = {}) {
super(options);
this.selectedEffectType = null;
@ -12,39 +12,39 @@ export default class FeatureSheet extends DaggerheartSheet(ItemSheetV2) {
static DEFAULT_OPTIONS = {
tag: 'form',
id: "daggerheart-feature",
classes: ["daggerheart", "sheet", "feature"],
id: 'daggerheart-feature',
classes: ['daggerheart', 'sheet', 'feature'],
position: { width: 600, height: 600 },
actions: {
addEffect: this.addEffect,
removeEffect: this.removeEffect,
addAction: this.addAction,
editAction: this.editAction,
removeAction: this.removeAction,
removeAction: this.removeAction
},
form: {
handler: this.updateForm,
submitOnChange: true,
closeOnSubmit: false,
},
closeOnSubmit: false
}
};
static PARTS = {
form: {
id: "feature",
template: "systems/daggerheart/templates/sheets/feature.hbs"
}
id: 'feature',
template: 'systems/daggerheart/templates/sheets/feature.hbs'
}
};
_getTabs() {
const tabs = {
features: { active: true, cssClass: '', group: 'primary', id: 'features', icon: null, label: 'Features' },
effects: { active: false, cssClass: '', group: 'primary', id: 'effects', icon: null, label: 'Effects' },
actions: { active: false, cssClass: '', group: 'primary', id: 'actions', icon: null, label: 'Actions' },
}
for ( const v of Object.values(tabs) ) {
actions: { active: false, cssClass: '', group: 'primary', id: 'actions', icon: null, label: 'Actions' }
};
for (const v of Object.values(tabs)) {
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;
@ -52,14 +52,13 @@ export default class FeatureSheet extends DaggerheartSheet(ItemSheetV2) {
_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) {
const context = await super._prepareContext(_options);
context.document = this.document;
context.tabs = this._getTabs(),
context.generalConfig = SYSTEM.GENERAL;
(context.tabs = this._getTabs()), (context.generalConfig = SYSTEM.GENERAL);
context.itemConfig = SYSTEM.ITEM;
context.properties = SYSTEM.ACTOR.featureProperties;
context.dice = SYSTEM.GENERAL.diceTypes;
@ -70,17 +69,17 @@ export default class FeatureSheet extends DaggerheartSheet(ItemSheetV2) {
}
static async updateForm(event, _, formData) {
await this.document.update(formData.object)
await this.document.update(formData.object);
this.render();
}
effectSelect(event){
effectSelect(event) {
this.selectedEffectType = event.currentTarget.value;
this.render(true);
}
static async addEffect(){
if(!this.selectedEffectType) return;
static async addEffect() {
if (!this.selectedEffectType) return;
const { id, name, ...rest } = SYSTEM.EFFECTS.effectTypes[this.selectedEffectType];
const update = {
@ -90,27 +89,33 @@ export default class FeatureSheet extends DaggerheartSheet(ItemSheetV2) {
...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}`;
await this.item.update({ [path]: null });
}
static async addAction(){
const action = await new DaggerheartAction({}, {parent: this.document});
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 addAction() {
const action = await new DaggerheartAction({}, { parent: this.document });
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];
await (new DaggerheartActionConfig(action)).render(true);
await new DaggerheartActionConfig(action).render(true);
}
static async removeAction(event, button){
static async removeAction(event, button) {
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) {
static DEFAULT_OPTIONS = {
tag: 'form',
id: "daggerheart-miscellaneous",
classes: ["daggerheart", "sheet", "miscellaneous"],
id: 'daggerheart-miscellaneous',
classes: ['daggerheart', 'sheet', 'miscellaneous'],
position: { width: 400 },
form: {
handler: this.updateForm,
submitOnChange: true,
closeOnSubmit: false,
},
closeOnSubmit: false
}
};
static PARTS = {
form: {
id: "feature",
template: "systems/daggerheart/templates/sheets/miscellaneous.hbs"
}
id: 'feature',
template: 'systems/daggerheart/templates/sheets/miscellaneous.hbs'
}
};
async _prepareContext(_options) {
const context = await super._prepareContext(_options);
@ -51,7 +51,7 @@ export default class MiscellaneousSheet extends DaggerheartSheet(ItemSheetV2) {
}
static async updateForm(event, _, formData) {
await this.document.update(formData.object)
await this.document.update(formData.object);
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) {
static DEFAULT_OPTIONS = {
tag: 'form',
id: "daggerheart-subclass",
classes: ["daggerheart", "sheet", "subclass"],
id: 'daggerheart-subclass',
classes: ['daggerheart', 'sheet', 'subclass'],
position: { width: 600 },
actions: {
editAbility: this.editAbility,
deleteFeatureAbility: this.deleteFeatureAbility,
deleteFeatureAbility: this.deleteFeatureAbility
},
form: {
handler: this.updateForm,
submitOnChange: true,
closeOnSubmit: false,
closeOnSubmit: false
},
dragDrop: [
{ dragSelector: null, dropSelector: '.foundation-tab' },
{ dragSelector: null, dropSelector: '.specialization-tab' },
{ dragSelector: null, dropSelector: '.mastery-tab' }
],
]
};
_getTabs() {
const tabs = {
general: { active: true, cssClass: '', 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') },
general: {
active: true,
cssClass: '',
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.cssClass = v.active ? "active" : "";
v.cssClass = v.active ? 'active' : '';
}
return tabs;
@ -115,10 +143,10 @@ export default class SubclassSheet extends DaggerheartSheet(ItemSheetV2) {
static PARTS = {
form: {
id: "feature",
template: "systems/daggerheart/templates/sheets/subclass.hbs"
}
id: 'feature',
template: 'systems/daggerheart/templates/sheets/subclass.hbs'
}
};
async _prepareContext(_options) {
const context = await super._prepareContext(_options);
@ -130,21 +158,23 @@ export default class SubclassSheet extends DaggerheartSheet(ItemSheetV2) {
}
static async updateForm(event, _, formData) {
await this.document.update(formData.object)
await this.document.update(formData.object);
this.render();
}
static async editAbility(_, button){
static async editAbility(_, button) {
const feature = await fromUuid(button.dataset.ability);
feature.sheet.render(true);
}
static async deleteFeatureAbility(event, button){
static async deleteFeatureAbility(event, button) {
event.preventDefault();
event.stopPropagation();
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`;
await this.document.update({ [path]: newAbilities });
@ -153,15 +183,25 @@ export default class SubclassSheet extends DaggerheartSheet(ItemSheetV2) {
async _onDrop(event) {
const data = TextEditor.getDragEventData(event);
const item = await fromUuid(data.uuid);
if(item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.subclass.id) {
if(event.currentTarget.classList.contains('foundation-tab')){
await this.document.update({ "system.foundationFeature.abilities": [...this.document.system.foundationFeature.abilities, item.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] });
if (item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.subclass.id) {
if (event.currentTarget.classList.contains('foundation-tab')) {
await this.document.update({
'system.foundationFeature.abilities': [
...this.document.system.foundationFeature.abilities,
item.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;
// }
// async _handleAction(action, event, button) {
// switch(action){
// }
@ -33,22 +32,22 @@ const { ItemSheetV2 } = foundry.applications.sheets;
export default class WeaponSheet extends DaggerheartSheet(ItemSheetV2) {
static DEFAULT_OPTIONS = {
tag: 'form',
id: "daggerheart-weapon",
classes: ["daggerheart", "sheet", "weapon"],
id: 'daggerheart-weapon',
classes: ['daggerheart', 'sheet', 'weapon'],
position: { width: 400 },
form: {
handler: this.updateForm,
submitOnChange: true,
closeOnSubmit: false,
},
closeOnSubmit: false
}
};
static PARTS = {
form: {
id: "feature",
template: "systems/daggerheart/templates/sheets/weapon.hbs"
}
id: 'feature',
template: 'systems/daggerheart/templates/sheets/weapon.hbs'
}
};
async _prepareContext(_options) {
const context = await super._prepareContext(_options);
@ -59,7 +58,7 @@ export default class WeaponSheet extends DaggerheartSheet(ItemSheetV2) {
}
static async updateForm(event, _, formData) {
await this.document.update(formData.object)
await this.document.update(formData.object);
this.render();
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,12 +1,12 @@
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 ITEM from './itemConfig.mjs';
import * as SETTINGS from './settingsConfig.mjs';
import * as EFFECTS from './effectConfig.mjs';
import * as ACTIONS from './actionConfig.mjs';
export const SYSTEM_ID = "daggerheart";
export const SYSTEM_ID = 'daggerheart';
export const SYSTEM = {
id: SYSTEM_ID,
@ -16,5 +16,5 @@ export const SYSTEM = {
ITEM,
SETTINGS,
EFFECTS,
ACTIONS,
ACTIONS
};

View file

@ -7,24 +7,26 @@ export default class DhpAbilityUse extends foundry.abstract.TypeDataModel {
img: new fields.StringField({}),
name: 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({}),
damage: new fields.SchemaField({
type: new fields.StringField({}),
value: new fields.StringField({}),
value: new fields.StringField({})
}),
healing: new fields.SchemaField({
type: new fields.StringField({}),
value: new fields.StringField({}),
value: new fields.StringField({})
}),
cost: new fields.SchemaField({
type: new fields.StringField({ nullable: true }),
value: new fields.NumberField({ nullable: true }),
value: new fields.NumberField({ nullable: true })
}),
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' }),
damage: new fields.SchemaField({
type: new fields.StringField({ choices: SYSTEM.GENERAL.damageTypes, nullable: true, initial: null }),
value: new fields.StringField({}),
value: new fields.StringField({})
}),
healing: new fields.SchemaField({
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(),
icon: new fields.StringField(),
description: new fields.StringField(),
})),
description: new fields.StringField()
})
),
cost: new fields.SchemaField({
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({
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({
// nr: new fields.StringField({}),
// refreshType: new fields.StringField({ choices: SYSTEM.GENERAL.refreshTypes, initial: SYSTEM.GENERAL.refreshTypes.session.id }),
// refreshed: new fields.BooleanField({ initial: true }),
// }),
}
};
}
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 {
static defineSchema() {
@ -8,16 +8,20 @@ export default class DhpAdversary extends foundry.abstract.TypeDataModel {
health: new fields.SchemaField({
value: 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({
value: 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 }),
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({}),
motivesAndTactics: new fields.ArrayField(new fields.StringField({})),
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 }),
damage: new fields.SchemaField({
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 }),
damageThresholds: new fields.SchemaField({
minor: 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({}),
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');
}
}

View file

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

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 {
static defineSchema() {
const fields = foundry.data.fields;
return {
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({
choices: SYSTEM.ITEM.armorFeatures,
integer: false,
blank: true,
blank: true
}),
marks: new fields.SchemaField({
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({
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() {
return this.feature
? CONFIG.daggerheart.ITEM.armorFeatures[this.feature]
: null;
return this.feature ? CONFIG.daggerheart.ITEM.armorFeatures[this.feature] : null;
}
prepareDerivedData() {

View file

@ -1,52 +1,67 @@
import { getTier } from "../helpers/utils.mjs";
import DhpFeature from "./feature.mjs";
import { getTier } from '../helpers/utils.mjs';
import DhpFeature from './feature.mjs';
export default class DhpClass extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
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({}),
img: new fields.StringField({}),
uuid: new fields.StringField({}),
})),
uuid: new fields.StringField({})
})
),
damageThresholds: new fields.SchemaField({
minor: 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}),
features: new fields.ArrayField(new fields.SchemaField({
evasion: new fields.NumberField({ initial: 0, integer: true }),
features: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}),
img: new fields.StringField({}),
uuid: new fields.StringField({}),
})),
subclasses: new fields.ArrayField(new fields.SchemaField({
uuid: new fields.StringField({})
})
),
subclasses: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}),
img: new fields.StringField({}),
uuid: new fields.StringField({}),
})),
uuid: new fields.StringField({})
})
),
inventory: new fields.SchemaField({
take: new fields.ArrayField(new fields.SchemaField({
take: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}),
img: new fields.StringField({}),
uuid: new fields.StringField({}),
})),
choiceA: new fields.ArrayField(new fields.SchemaField({
uuid: new fields.StringField({})
})
),
choiceA: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}),
img: new fields.StringField({}),
uuid: new fields.StringField({}),
})),
choiceB: new fields.ArrayField(new fields.SchemaField({
uuid: new fields.StringField({})
})
),
choiceB: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}),
img: new fields.StringField({}),
uuid: new fields.StringField({}),
})),
extra: new fields.SchemaField({
uuid: new fields.StringField({})
})
),
extra: new fields.SchemaField(
{
title: new fields.StringField({}),
description: new fields.StringField({})
}, { initial: null, nullable: true }),
},
{ initial: null, nullable: true }
)
}),
characterGuide: 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 }),
instinct: 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({}),
img: new fields.StringField({}),
uuid: new fields.StringField({}),
}, { initial: null, nullable: true }),
suggestedSecondaryWeapon: new fields.SchemaField({
uuid: new fields.StringField({})
},
{ initial: null, nullable: true }
),
suggestedSecondaryWeapon: new fields.SchemaField(
{
name: new fields.StringField({}),
img: new fields.StringField({}),
uuid: new fields.StringField({}),
}, { initial: null, nullable: true }),
suggestedArmor: new fields.SchemaField({
uuid: new fields.StringField({})
},
{ initial: null, nullable: true }
),
suggestedArmor: new fields.SchemaField(
{
name: new fields.StringField({}),
img: new fields.StringField({}),
uuid: new fields.StringField({}),
}, { initial: null, nullable: true }),
uuid: new fields.StringField({})
},
{ initial: null, nullable: true }
),
characterDescription: new fields.SchemaField({
clothes: new fields.StringField({}),
eyes: new fields.StringField({}),
body: new fields.StringField({}),
color: new fields.StringField({}),
attitude: new fields.StringField({}),
attitude: new fields.StringField({})
}),
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 }),
description: new fields.HTMLField({}),
}
description: new fields.HTMLField({})
};
}
get multiclassTier(){
get multiclassTier() {
return getTier(this.multiclass, true);
}
}

View file

@ -3,7 +3,7 @@ export default class DhpCombat extends foundry.abstract.TypeDataModel {
const fields = foundry.data.fields;
return {
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;
return {
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 {
static defineSchema() {
const fields = foundry.data.fields;
return {
description: new fields.HTMLField({}),
abilities: featuresSchema(),
}
abilities: featuresSchema()
};
}
}

View file

@ -4,7 +4,7 @@ export default class DhpConsumable extends foundry.abstract.TypeDataModel {
return {
description: new fields.HTMLField({}),
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 {
static defineSchema() {
const fields = foundry.data.fields;
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 }),
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 }),
effect: new fields.HTMLField({}),
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 diceField = () => new fields.SchemaField({
const diceField = () =>
new fields.SchemaField({
dice: new fields.StringField({}),
value: new fields.NumberField({ integer: true}),
});
value: new fields.NumberField({ integer: true })
});
export default class DhpDualityRoll extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
roll: new fields.StringField({}),
modifiers: new fields.ArrayField(new fields.SchemaField({
modifiers: new fields.ArrayField(
new fields.SchemaField({
value: new fields.NumberField({ integer: true }),
label: new fields.StringField({}),
title: new fields.StringField({}),
})),
title: new fields.StringField({})
})
),
hope: diceField(),
fear: diceField(),
advantage: diceField(),
disadvantage: diceField(),
advantageSelected: new fields.NumberField({ initial: 0 }),
targets: new fields.ArrayField(new fields.SchemaField({
targets: new fields.ArrayField(
new fields.SchemaField({
id: new fields.StringField({}),
name: new fields.StringField({}),
img: new fields.StringField({}),
difficulty: new fields.NumberField({ integer: true, nullable: true }),
evasion: new fields.NumberField({ integer: true }),
hit: new fields.BooleanField({ initial: false }),
})),
hit: new fields.BooleanField({ initial: false })
})
),
damage: new fields.SchemaField({
value: new fields.StringField({}),
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({}),
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(),
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({}),
hopeIncrease: new fields.StringField({ nullable: true })
}), { nullable: true, initial: null })
}),
{ nullable: true, initial: null }
)
})
}
};
}
get total() {
const modifiers = this.modifiers.reduce((acc, x) => acc+x.value, 0);
const advantage = this.advantage.value ?? this.disadvantage.value ? -this.disadvantage.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;
return this.hope.value + this.fear.value + advantage + modifiers;
}
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);
}
prepareDerivedData(){
prepareDerivedData() {
const total = this.total;
this.targets.forEach(target => {

View file

@ -2,19 +2,21 @@ export default class DhpEnvironment extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
resources: new fields.SchemaField({
}),
resources: new fields.SchemaField({}),
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({}),
toneAndFeel: new fields.StringField({}),
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');
}
}

View file

@ -1,70 +1,99 @@
import { getTier } from "../helpers/utils.mjs";
import DaggerheartAction from "./action.mjs";
import { MappingField } from "./fields.mjs";
import DhpEffect from "./interface/effects.mjs";
import { getTier } from '../helpers/utils.mjs';
import DaggerheartAction from './action.mjs';
import { MappingField } from './fields.mjs';
import DhpEffect from './interface/effects.mjs';
export default class DhpFeature extends DhpEffect {
static defineSchema() {
const fields = foundry.data.fields;
return foundry.utils.mergeObject({}, {
return foundry.utils.mergeObject(
{},
{
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({
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({
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 }),
numbers: new MappingField(new fields.SchemaField({
numbers: new MappingField(
new fields.SchemaField({
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 }),
uses: new fields.NumberField({ initial: 1, integer: 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 }),
disabled: new fields.BooleanField({ initial: false }),
description: new fields.HTMLField({}),
effects: new MappingField(new fields.SchemaField({
effects: new MappingField(
new fields.SchemaField({
type: new fields.StringField({ choices: SYSTEM.EFFECTS.effectTypes }),
valueType: new fields.StringField({ choices: SYSTEM.EFFECTS.valueTypes }),
parseType: new fields.StringField({ choices: SYSTEM.EFFECTS.parseTypes }),
initiallySelected: new fields.BooleanField({ initial: true }),
options: new fields.ArrayField(new fields.SchemaField({
options: new fields.ArrayField(
new fields.SchemaField({
name: new fields.StringField({}),
value: new fields.StringField({}),
}), { nullable: true, initial: null }),
value: new fields.StringField({})
}),
{ nullable: true, initial: null }
),
dataField: new fields.StringField({}),
appliesOn: new fields.StringField({ choices: SYSTEM.EFFECTS.applyLocations }, { nullable: true, initial: null }),
applyLocationChoices: new MappingField(new fields.StringField({}), { nullable: true, initial: null }),
appliesOn: new fields.StringField(
{ choices: SYSTEM.EFFECTS.applyLocations },
{ nullable: true, initial: null }
),
applyLocationChoices: new MappingField(new fields.StringField({}), {
nullable: true,
initial: null
}),
valueData: new fields.SchemaField({
value: new fields.StringField({}),
fromValue: new fields.StringField({ initial: null, nullable: true }),
type: 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);
}
async refresh(){
if(this.refreshData){
if(this.featureType.type === SYSTEM.ITEM.valueTypes.dice.id) {
const update = { "system.refreshData.refreshed": true };
Object.keys(this.featureType.data.numbers).forEach(x => update[`system.featureType.data.numbers.-=${x}`] = null);
async refresh() {
if (this.refreshData) {
if (this.featureType.type === SYSTEM.ITEM.valueTypes.dice.id) {
const update = { 'system.refreshData.refreshed': true };
Object.keys(this.featureType.data.numbers).forEach(
x => (update[`system.featureType.data.numbers.-=${x}`] = null)
);
await this.parent.update(update);
}
else {
await this.parent.update({ "system.refreshData.refreshed": true});
} else {
await this.parent.update({ 'system.refreshData.refreshed': true });
}
}
}

View file

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

View file

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

View file

@ -1,10 +1,13 @@
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({}),
img: new fields.StringField({}),
uuid: new fields.StringField({}),
subclassLevel: new fields.StringField({}),
}))
subclassLevel: new fields.StringField({})
})
);
export default featuresSchema;

View file

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

View file

@ -1,19 +1,20 @@
import { getPathValue, getTier } from "../helpers/utils.mjs";
import { MappingField } from "./fields.mjs";
import { getPathValue, getTier } from '../helpers/utils.mjs';
import { MappingField } from './fields.mjs';
const fields = foundry.data.fields;
const attributeField = () => new fields.SchemaField({
const attributeField = () =>
new fields.SchemaField({
data: new fields.SchemaField({
value: new fields.NumberField({ initial: 0, integer: true }),
base: new fields.NumberField({ initial: 0, integer: true }),
bonus: 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 })),
levelMark: new fields.NumberField({ nullable: true, initial: null, integer: true }),
});
levelMark: new fields.NumberField({ nullable: true, initial: null, integer: true })
});
const levelUpTier = () => ({
attributes: new MappingField(new fields.BooleanField()),
@ -26,11 +27,13 @@ const levelUpTier = () => ({
severeDamageThreshold2: new MappingField(new fields.BooleanField()),
severeDamageThreshold3: 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(),
feature: new fields.StringField({}),
})),
multiclass: new MappingField(new fields.BooleanField()),
feature: new fields.StringField({})
})
),
multiclass: new MappingField(new fields.BooleanField())
});
// const weapon = () => new fields.SchemaField({
@ -53,26 +56,28 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
health: new fields.SchemaField({
value: 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({
value: 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({
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({
damage: new fields.ArrayField(new fields.SchemaField({
damage: new fields.ArrayField(
new fields.SchemaField({
value: new fields.NumberField({ integer: true, initial: 0 }),
type: new fields.StringField({ nullable: true }),
initiallySelected: new fields.BooleanField(),
hopeIncrease: new fields.StringField({ initial: null, nullable: true }),
description: new fields.StringField({}),
})),
description: new fields.StringField({})
})
)
}),
attributes: new fields.SchemaField({
agility: attributeField(),
@ -80,145 +85,178 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
finesse: attributeField(),
instinct: attributeField(),
presence: attributeField(),
knowledge: attributeField(),
knowledge: attributeField()
}),
proficiency: new fields.SchemaField({
value: new fields.NumberField({ initial: 1, integer: true}),
min: new fields.NumberField({ initial: 1, integer: true}),
max: new fields.NumberField({ initial: 6, integer: true}),
value: new fields.NumberField({ initial: 1, integer: true }),
min: new fields.NumberField({ initial: 1, integer: true }),
max: new fields.NumberField({ initial: 6, integer: true })
}),
damageThresholds: new fields.SchemaField({
minor: 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 }),
// armor: new fields.SchemaField({
// value: new fields.NumberField({ initial: 0, integer: 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 }),
level: new fields.NumberField({ required: true, integer: true }),
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: [
{ 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({
coins: new fields.NumberField({ initial: 0, integer: true }),
handfulls: 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({}),
domainData: new fields.SchemaField({
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({
currentLevel: 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 }),
tier1: new fields.SchemaField({
...levelUpTier()
}),
tier2: new fields.SchemaField({
tier2: new fields.SchemaField(
{
...levelUpTier()
}, { nullable: true, initial: null }),
tier3: new fields.SchemaField({
},
{ nullable: true, initial: null }
),
tier3: new fields.SchemaField(
{
...levelUpTier()
}, { nullable: true, initial: null }),
})),
},
{ nullable: true, initial: null }
)
})
)
}),
story: new fields.SchemaField({
background: new fields.HTMLField(),
appearance: 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({}),
description: new fields.HTMLField(),
})),
description: new fields.HTMLField()
})
)
}),
description: new fields.StringField({}),
//Temporary until new FoundryVersion fix --> See Armor.Mjs DataPreparation
armorMarks: new fields.SchemaField({
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 this.levelData.currentLevel !== this.levelData.changedLevel;
}
get tier(){
get tier() {
return this.#getTier(this.levelData.currentLevel);
}
get ancestry(){
get ancestry() {
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;
}
get multiclass(){
get multiclass() {
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;
}
get subclass(){
get subclass() {
return this.parent.items.find(x => x.type === 'subclass' && !x.system.multiclass) ?? null;
}
get subclassFeatures(){
get subclassFeatures() {
const subclass = this.subclass;
const multiclass = this.multiclassSubclass;
const subclassItems = this.parent.items.filter(x => x.type === 'feature' && x.system.type === 'subclass');
return {
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)),
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)
)
},
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)),
}
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)
)
}
};
}
get community(){
get community() {
return this.parent.items.find(x => x.type === 'community') ?? null;
}
get classFeatures(){
return this.parent.items.filter(x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.class.id && !x.system.multiclass);
get classFeatures() {
return this.parent.items.filter(
x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.class.id && !x.system.multiclass
);
}
get multiclassFeatures(){
return this.parent.items.filter(x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.class.id && x.system.multiclass);
get multiclassFeatures() {
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 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 loadout = 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');
}
get activeWeapons(){
const primaryWeapon = this.parent.items.find(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);
get activeWeapons() {
const primaryWeapon = this.parent.items.find(
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 {
primary: this.#weaponData(primaryWeapon),
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 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 {
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) => {
const nrAttributeMarks = Object.keys(this.levelData.levelups[level]).reduce((nr, tier) => {
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);
return this.totalAttributeMarks.reduce((acc, attribute) => {
if(!attributeMarks.findSplice(x => x === attribute)){
if (!attributeMarks.findSplice(x => x === 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) => {
const effects = item.system.effectData;
if(effects && !item.system.disabled){
for(var key in effects){
if (effects && !item.system.disabled) {
for (var key in effects) {
const effect = effects[key];
for(var effectEntry of effect){
if(!acc[key]) acc[key] = [];
for (var effectEntry of effect) {
if (!acc[key]) acc[key] = [];
acc[key].push({ name: item.name, value: effectEntry });
}
}
@ -295,45 +339,52 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
}, {});
}
get refreshableFeatures(){
return this.parent.items.reduce((acc, x) => {
if(x.type === 'feature' && x.system.refreshData.type){
get refreshableFeatures() {
return this.parent.items.reduce(
(acc, x) => {
if (x.type === 'feature' && x.system.refreshData.type) {
acc[x.system.refreshData.type].push(x);
}
return acc;
}, { shortRest: [], longRest: [] });
},
{ shortRest: [], longRest: [] }
);
}
#weaponData(weapon){
return weapon ? {
#weaponData(weapon) {
return weapon
? {
name: weapon.name,
trait: CONFIG.daggerheart.ACTOR.abilities[weapon.system.trait].name, //Should not be done in data?
range: CONFIG.daggerheart.GENERAL.range[weapon.system.range],
damage: {
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],
img: weapon.img,
uuid: weapon.uuid
} : null
}
: null;
}
prepareDerivedData(){
prepareDerivedData() {
this.resources.hope.max = 6 - this.story.scars.length;
if(this.resources.hope.value >= this.resources.hope.max){
this.resources.hope.value = Math.max(this.resources.hope.max-1, 0);
if (this.resources.hope.value >= this.resources.hope.max) {
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];
attribute.levelMark = attribute.levelMarks.find(x => this.isSameTier(x)) ?? null;
const actualValue = attribute.data.base + attribute.levelMarks.length + attribute.data.bonus;
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;
@ -344,30 +395,50 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
this.applyEffects();
}
applyLevels(){
let healthBonus = 0, stressBonus = 0, proficiencyBonus = 0, evasionBonus = 0, armorBonus = 0, minorThresholdBonus = 0, majorThresholdBonus = 0, severeThresholdBonus = 0;
applyLevels() {
let healthBonus = 0,
stressBonus = 0,
proficiencyBonus = 0,
evasionBonus = 0,
armorBonus = 0,
minorThresholdBonus = 0,
majorThresholdBonus = 0,
severeThresholdBonus = 0;
let experienceBonuses = {};
let advancementFirst = null, advancementSecond = null;
for(var level in this.levelData.levelups){
let advancementFirst = null,
advancementSecond = null;
for (var level in this.levelData.levelups) {
var levelData = this.levelData.levelups[level];
for(var tier in levelData){
for (var tier in levelData) {
var tierData = levelData[tier];
if(tierData){
if (tierData) {
healthBonus += Object.keys(tierData.hitPointSlots).length;
stressBonus += Object.keys(tierData.stressSlots).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;
advancementSecond = Object.keys(tierData.subclass).length > 0 && (level >= 8 && level <= 10) ? { ...tierData.subclass[0], tier: getTier(Number.parseInt(level), true) } : advancementSecond;
advancementFirst =
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 experienceKey in tierData.experiences[index]){
for (var index in Object.keys(tierData.experiences)) {
for (var experienceKey in tierData.experiences[index]) {
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;
armorBonus += Object.keys(tierData.armorOrEvasionSlot).filter(x => tierData.armorOrEvasionSlot[x] === 'armor').length;
evasionBonus += Object.keys(tierData.armorOrEvasionSlot).filter(
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;
severeThresholdBonus += Object.keys(tierData.severeDamageThreshold2).length * 2;
@ -383,7 +454,7 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
this.evasion += evasionBonus;
this.armorMarks = {
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.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) }));
const subclassFeatures = this.subclassFeatures;
if(advancementFirst){
if(advancementFirst.multiclass){
if (advancementFirst) {
if (advancementFirst.multiclass) {
this.multiclassSubclass.system[`${advancementFirst.feature}Feature`].unlocked = true;
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 {
this.subclass.system[`${advancementFirst.feature}Feature`].unlocked = true;
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.multiclass){
if (advancementSecond) {
if (advancementSecond.multiclass) {
this.multiclassSubclass.system[`${advancementSecond.feature}Feature`].unlocked = true;
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 {
this.subclass.system[`${advancementSecond.feature}Feature`].unlocked = true;
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
for(var i = 0; i < this.levelData.currentLevel; i++){
const tier = getTier(i+1);
if(tier !== 'tier0'){
this.domainData.maxLoadout = Math.min(this.domainData.maxLoadout+1, 5);
for (var i = 0; i < this.levelData.currentLevel; i++) {
const tier = getTier(i + 1);
if (tier !== 'tier0') {
this.domainData.maxLoadout = Math.min(this.domainData.maxLoadout + 1, 5);
this.domainData.maxCards += 1;
}
switch(tier){
switch (tier) {
case 'tier1':
this.damageThresholds.severe += 2;
break;
@ -440,12 +512,12 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
}
}
applyEffects(){
applyEffects() {
const effects = this.effects;
for(var key in effects){
for (var key in effects) {
const effectType = effects[key];
for(var effect of effectType) {
switch(key) {
for (var effect of effectType) {
switch (key) {
case SYSTEM.EFFECTS.effectTypes.health.id:
this.resources.health.max += effect.value.valueData.value;
break;
@ -459,39 +531,32 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
description: effect.name,
hopeIncrease: effect.value.valueData.hopeIncrease,
initiallySelected: effect.value.initiallySelected,
appliesOn: effect.value.appliesOn,
appliesOn: effect.value.appliesOn
});
}
}
}
}
getBurden(primary, secondary){
getBurden(primary, secondary) {
const twoHanded =
primary?.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 =
!twoHanded &&
(
primary?.system?.burden === 'oneHanded' ||
secondary?.system?.burden === 'oneHanded'
);
!twoHanded && (primary?.system?.burden === 'oneHanded' || secondary?.system?.burden === 'oneHanded');
return twoHanded ? 'twoHanded' : oneHanded ? 'oneHanded' : null;
}
isSameTier(level){
isSameTier(level) {
return this.#getTier(this.levelData.currentLevel) === this.#getTier(level);
}
#getTier(level){
if(level >= 8) return 3;
else if(level >= 5) return 2;
else if(level >= 2) return 1;
#getTier(level) {
if (level >= 8) return 3;
else if (level >= 5) return 2;
else if (level >= 2) return 1;
else return 0;
}
}

View file

@ -1,5 +1,5 @@
import { getTier } from "../helpers/utils.mjs";
import featuresSchema from "./interface/featuresSchema.mjs";
import { getTier } from '../helpers/utils.mjs';
import featuresSchema from './interface/featuresSchema.mjs';
import DaggerheartFeature from './feature.mjs';
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;
return {
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({
description: new fields.HTMLField({}),
abilities: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartFeature)),
abilities: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartFeature))
}),
specializationFeature: new fields.SchemaField({
unlocked: new fields.BooleanField({ initial: false }),
tier: new fields.NumberField({ initial: null, nullable: true, integer: true }),
description: new fields.HTMLField({}),
abilities: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartFeature)),
abilities: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartFeature))
}),
masteryFeature: new fields.SchemaField({
unlocked: new fields.BooleanField({ initial: false }),
tier: new fields.NumberField({ initial: null, nullable: true, integer: true }),
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);
}
}

View file

@ -9,29 +9,32 @@ export default class DhpWeapon extends foundry.abstract.TypeDataModel {
range: new fields.StringField({ choices: SYSTEM.GENERAL.range, integer: false }),
damage: new fields.SchemaField({
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 }),
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 }),
description: new fields.HTMLField({}),
}
description: new fields.HTMLField({})
};
}
prepareDerivedData(){
if(this.parent.parent){
prepareDerivedData() {
if (this.parent.parent) {
this.applyEffects();
}
}
applyEffects(){
applyEffects() {
const effects = this.parent.parent.system.effects;
for(var key in effects){
for (var key in effects) {
const effectType = effects[key];
for(var effect of effectType) {
switch(key) {
for (var effect of effectType) {
switch (key) {
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;
}

View file

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

View file

@ -1,27 +1,30 @@
import DamageSelectionDialog from "../applications/damageSelectionDialog.mjs";
import NpcRollSelectionDialog from "../applications/npcRollSelectionDialog.mjs";
import RollSelectionDialog from "../applications/rollSelectionDialog.mjs";
import { GMUpdateEvent, socketEvent } from "../helpers/socket.mjs";
import DamageSelectionDialog from '../applications/damageSelectionDialog.mjs';
import NpcRollSelectionDialog from '../applications/npcRollSelectionDialog.mjs';
import RollSelectionDialog from '../applications/rollSelectionDialog.mjs';
import { GMUpdateEvent, socketEvent } from '../helpers/socket.mjs';
export default class DhpActor extends Actor {
_preCreate(data, changes, user){
if(data.type === 'pc'){
_preCreate(data, changes, user) {
if (data.type === 'pc') {
data.prototypeToken = { actorLink: true, disposition: 1, sight: { enabled: true } };
}
super._preCreate(data, changes, user);
}
prepareData(){
prepareData() {
super.prepareData();
}
async _preUpdate(changed, options, user) {
//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.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;
}
@ -29,16 +32,25 @@ export default class DhpActor extends Actor {
}, {});
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;
}, {});
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);
for(var feature of multiclassFeatures){
for (var feature of multiclassFeatures) {
await feature.delete();
}
}
@ -48,10 +60,9 @@ export default class DhpActor extends Actor {
}
async diceRoll(modifier, shiftKey) {
if(this.type === 'pc'){
if (this.type === 'pc') {
return await this.dualityRoll(modifier, shiftKey);
}
else {
} else {
return await this.npcRoll(modifier, shiftKey);
}
}
@ -64,10 +75,10 @@ export default class DhpActor extends Actor {
{
value: Number.parseInt(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, _) => {
new NpcRollSelectionDialog(this.system.experiences, resolve).render(true);
});
@ -75,133 +86,183 @@ export default class DhpActor extends Actor {
nrDice = result.nrDice;
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();
const diceResults = rollResult.dice.flatMap(x => x.results.flatMap(result => ({ value: result.result })));
return { roll, diceResults: diceResults, modifiers: modifiers };
}
async dualityRoll(modifier, shiftKey, bonusDamage=[]){
let hopeDice = 'd12', fearDice = 'd12', advantageDice = null, disadvantageDice = null, bonusDamageString = "";
async dualityRoll(modifier, shiftKey, bonusDamage = []) {
let hopeDice = 'd12',
fearDice = 'd12',
advantageDice = null,
disadvantageDice = null,
bonusDamageString = '';
const modifiers = [
{
value: modifier.value ? Number.parseInt(modifier.value) : 0,
label: modifier.value >= 0 ? `+${modifier.value}` : `-${modifier.value}`,
title: modifier.title,
title: modifier.title
}
];
if(!shiftKey) {
if (!shiftKey) {
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;
hopeDice = result.hope, 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 }))
(hopeDice = result.hope),
(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;
const automateHope = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope);
if(automateHope && result.hopeUsed){
await this.update({ "system.resources.hope.value": this.system.resources.hope.value - result.hopeUsed });
if (automateHope && 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();
rollResult.dice[0].options.appearance = {
colorset:"inspired",
foreground: "#FFFFFF",
background: "#008080",
outline: "#000000",
edge: "#806400",
texture: "bloodmoon",
material: "metal",
font: "Arial Black",
system: "standard"
colorset: 'inspired',
foreground: '#FFFFFF',
background: '#008080',
outline: '#000000',
edge: '#806400',
texture: 'bloodmoon',
material: 'metal',
font: 'Arial Black',
system: 'standard'
};
if(advantageDice || disadvantageDice){
if (advantageDice || disadvantageDice) {
rollResult.dice[1].options.appearance = {
colorset:"inspired",
foreground: disadvantageDice ? "#b30000" : "#FFFFFF",
background: "#008080",
outline: disadvantageDice ? "#000000" : "#000000",
edge: "#806400",
texture: "bloodmoon",
material: "metal",
font: "Arial Black",
system: "standard"
colorset: 'inspired',
foreground: disadvantageDice ? '#b30000' : '#FFFFFF',
background: '#008080',
outline: disadvantageDice ? '#000000' : '#000000',
edge: '#806400',
texture: 'bloodmoon',
material: 'metal',
font: 'Arial Black',
system: 'standard'
};
rollResult.dice[2].options.appearance = {
colorset:"bloodmoon",
foreground: "#000000",
background: "#430070",
outline: "#b30000",
edge: "#000000",
texture: "bloodmoon",
material: "metal",
font: "Arial Black",
system: "standard"
colorset: 'bloodmoon',
foreground: '#000000',
background: '#430070',
outline: '#b30000',
edge: '#000000',
texture: 'bloodmoon',
material: 'metal',
font: 'Arial Black',
system: 'standard'
};
}
else {
} else {
rollResult.dice[1].options.appearance = {
colorset:"bloodmoon",
foreground: "#000000",
background: "#430070",
outline: "#b30000",
edge: "#000000",
texture: "bloodmoon",
material: "metal",
font: "Arial Black",
system: "standard"
colorset: 'bloodmoon',
foreground: '#000000',
background: '#430070',
outline: '#b30000',
edge: '#000000',
texture: 'bloodmoon',
material: 'metal',
font: 'Arial Black',
system: 'standard'
};
}
const hope = rollResult.dice[0].results[0].result;
const advantage = advantageDice ? 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){
rollResult = {...rollResult, total: rollResult.total - Math.max(hope, disadvantage) };
if (disadvantage) {
rollResult = { ...rollResult, total: rollResult.total - Math.max(hope, disadvantage) };
}
if(advantage){
rollResult = {...rollResult, total: 'Select Hope Die' };
if (advantage) {
rollResult = { ...rollResult, total: 'Select Hope Die' };
}
const automateHope = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope);
if (automateHope && hope > fear){
await this.update({ "system.resources.hope.value": Math.min(this.system.resources.hope.value+1, this.system.resources.hope.max) });
if (automateHope && hope > fear) {
await this.update({
'system.resources.hope.value': Math.min(
this.system.resources.hope.value + 1,
this.system.resources.hope.max
)
});
}
if(automateHope && hope === fear){
await this.update({ "system.resources": {
"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),
}});
if (automateHope && hope === fear) {
await this.update({
'system.resources': {
'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 bonusDamage = damage.bonusDamage?.filter(x => x.initiallySelected) ?? [];
if(!shiftKey) {
if (!shiftKey) {
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;
bonusDamage = result.bonusDamage;
rollString = result.rollString;
const automateHope = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope);
if(automateHope && result.hopeUsed){
await this.update({ "system.resources.hope.value": this.system.resources.hope.value - result.hopeUsed });
if (automateHope && 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 modifiers = [];
for(var i = 0; i < rollResult.terms.length; i++){
for (var i = 0; i < rollResult.terms.length; i++) {
const term = rollResult.terms[i];
if(term.faces){
dice.push({type: `d${term.faces}`, value: term.total});
}
else if (term.operator){
}
else if(term.number){
const operator = i === 0 ? '' : rollResult.terms[i-1].operator;
if (term.faces) {
dice.push({ type: `d${term.faces}`, value: term.total });
} else if (term.operator) {
} else if (term.number) {
const operator = i === 0 ? '' : rollResult.terms[i - 1].operator;
modifiers.push(`${operator}${term.number}`);
}
}
const cls = getDocumentClass("ChatMessage");
const cls = getDocumentClass('ChatMessage');
const msg = new cls({
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,
total: rollResult.total,
dice: dice,
@ -239,16 +297,24 @@ export default class DhpActor extends Actor {
cls.create(msg.toObject());
}
async takeDamage(damage, type){
async takeDamage(damage, type) {
const hpDamage =
damage >= this.system.damageThresholds.severe ? 3 :
damage >= this.system.damageThresholds.major ? 2 :
damage >= this.system.damageThresholds.minor ? 1 :
0;
damage >= this.system.damageThresholds.severe
? 3
: damage >= this.system.damageThresholds.major
? 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);
} else {
await game.socket.emit(`system.${SYSTEM.id}`, {
@ -256,24 +322,24 @@ export default class DhpActor extends Actor {
data: {
action: GMUpdateEvent.UpdateDocument,
uuid: this.uuid,
update: update,
update: update
}
});
}
}
async takeHealing(healing, type) {
let update = { };
switch(type){
let update = {};
switch (type) {
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;
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;
}
if(game.user.isGM){
if (game.user.isGM) {
await this.update(update);
} else {
await game.socket.emit(`system.${SYSTEM.id}`, {
@ -281,67 +347,67 @@ export default class DhpActor extends Actor {
data: {
action: GMUpdateEvent.UpdateDocument,
uuid: this.uuid,
update: update,
update: update
}
});
}
}
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 });
}
//Move to action-scope?
async useAction(action) {
const userTargets = Array.from(game.user.targets);
const otherTarget = action.target.type ===SYSTEM.ACTIONS.targetTypes.other.id;
if(otherTarget && userTargets.length === 0) {
ui.notifications.error(game.i18n.localize("DAGGERHEART.Notification.Error.ActionRequiresTarget"));
const otherTarget = action.target.type === SYSTEM.ACTIONS.targetTypes.other.id;
if (otherTarget && userTargets.length === 0) {
ui.notifications.error(game.i18n.localize('DAGGERHEART.Notification.Error.ActionRequiresTarget'));
return;
}
if(action.cost.type != null && action.cost.value != null){
if (this.system.resources[action.cost.type].value < action.cost.value-1) {
if (action.cost.type != null && action.cost.value != null) {
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`));
return;
}
}
// 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 };
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();
}
const cls = getDocumentClass("ChatMessage");
const cls = getDocumentClass('ChatMessage');
const msg = new cls({
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,
total: roll.result,
type: action.damage.type,
}),
type: action.damage.type
})
});
cls.create(msg.toObject());
}
if(action.healing.type){
if (action.healing.type) {
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();
}
const cls = getDocumentClass("ChatMessage");
const cls = getDocumentClass('ChatMessage');
const msg = new cls({
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,
total: roll.result,
type: action.healing.type,
}),
type: action.healing.type
})
});
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 {
_sortCombatants(a, b) {
if(a.isNPC !== b.isNPC){
if (a.isNPC !== b.isNPC) {
const aVal = a.isNPC ? 0 : 1;
const bVal = b.isNPC ? 0 : 1;
@ -13,20 +13,23 @@ export default class DhpCombat extends Combat {
}
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(this.system.actions < 1) return;
if (game.user.isGM) {
if (this.system.actions < 1) return;
const update = automateActionPoints ?
{ "system.activeCombatant": combatantId, "system.actions": Math.max(this.system.actions-1, 0) } :
{ "system.activeCombatant": combatantId };
const update = automateActionPoints
? { 'system.activeCombatant': combatantId, 'system.actions': Math.max(this.system.actions - 1, 0) }
: { 'system.activeCombatant': combatantId };
await this.update(update);
} else {
const update = automateActionPoints ?
{ "system.activeCombatant": combatantId, "system.actions": this.system.actions+1} :
{ "system.activeCombatant": combatantId };
const update = automateActionPoints
? { 'system.activeCombatant': combatantId, 'system.actions': this.system.actions + 1 }
: { 'system.activeCombatant': combatantId };
await game.socket.emit(`system.${SYSTEM.id}`, {
action: socketEvent.GMUpdate,

View file

@ -1,18 +1,18 @@
export default class DhpItem extends Item {
_preCreate(data, changes, user){
_preCreate(data, changes, user) {
super._preCreate(data, changes, user);
}
prepareData(){
prepareData() {
super.prepareData();
if(this.type === 'class'){
if (this.type === 'class') {
// Bad. Make this better.
// 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);
}
@ -24,13 +24,13 @@ export default class DhpItem extends Item {
const documentName = this.metadata.name;
const types = game.documentTypes[documentName].filter(t => t !== CONST.BASE_DOCUMENT_TYPE);
let collection;
if ( !parent ) {
if ( pack ) collection = game.packs.get(pack);
if (!parent) {
if (pack) collection = game.packs.get(pack);
else collection = game.collections.get(documentName);
}
const folders = collection?._formatFolderSelectOptions() ?? [];
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 label = CONFIG[documentName]?.typeLabels?.[t] ?? 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
const html = await renderTemplate("systems/daggerheart/templates/sidebar/documentCreate.hbs", {
const html = await renderTemplate('systems/daggerheart/templates/sidebar/documentCreate.hbs', {
folders,
name: data.name || game.i18n.format("DOCUMENT.New", {type: label}),
name: data.name || game.i18n.format('DOCUMENT.New', { type: label }),
folder: data.folder,
hasFolders: folders.length >= 1,
type: data.type || CONFIG[documentName]?.defaultType || typeObjects.armor,
types: {
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
});
@ -57,16 +64,16 @@ export default class DhpItem extends Item {
content: html,
label: title,
callback: html => {
const form = html[0].querySelector("form");
const form = html[0].querySelector('form');
const fd = new FormDataExtended(form);
foundry.utils.mergeObject(data, fd.object, {inplace: true});
if ( !data.folder ) delete data.folder;
if ( types.length === 1 ) data.type = types[0];
if ( !data.name?.trim() ) data.name = this.defaultName();
return this.create(data, {parent, pack, renderSheet: true});
foundry.utils.mergeObject(data, fd.object, { inplace: true });
if (!data.folder) delete data.folder;
if (types.length === 1) data.type = types[0];
if (!data.name?.trim()) data.name = this.defaultName();
return this.create(data, { parent, pack, renderSheet: true });
},
rejectClose: false,
options
});
}
}
}

View file

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

View file

@ -1,7 +1,7 @@
export const loadCompendiumOptions = async (compendiums) => {
export const loadCompendiumOptions = async compendiums => {
const compendiumValues = [];
for(var compendium of compendiums){
for (var compendium of compendiums) {
const values = await getCompendiumOptions(compendium);
compendiumValues.push(values);
}
@ -9,11 +9,11 @@ export const loadCompendiumOptions = async (compendiums) => {
return compendiumValues;
};
const getCompendiumOptions = async (compendium) => {
const getCompendiumOptions = async compendium => {
const compendiumPack = await game.packs.get(compendium);
const values = [];
for(var value of compendiumPack.index){
for (var value of compendiumPack.index) {
const document = await compendiumPack.getDocument(value._id);
values.push(document);
}
@ -34,23 +34,22 @@ export const getWidthOfText = (txt, fontsize, allCaps, bold) => {
// getWidthOfText.e.innerText = txt;
// return getWidthOfText.e.offsetWidth;
const text = allCaps ? txt.toUpperCase() : txt;
if(getWidthOfText.c === undefined){
getWidthOfText.c=document.createElement('canvas');
getWidthOfText.ctx=getWidthOfText.c.getContext('2d');
if (getWidthOfText.c === undefined) {
getWidthOfText.c = document.createElement('canvas');
getWidthOfText.ctx = getWidthOfText.c.getContext('2d');
}
var fontspec = `${bold ? 'bold': ''} ${fontsize}px` + ' ' + 'Signika, sans-serif';
if(getWidthOfText.ctx.font !== fontspec)
getWidthOfText.ctx.font = fontspec;
var fontspec = `${bold ? 'bold' : ''} ${fontsize}px` + ' ' + 'Signika, sans-serif';
if (getWidthOfText.ctx.font !== fontspec) getWidthOfText.ctx.font = fontspec;
return getWidthOfText.ctx.measureText(text).width;
}
};
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) => {
switch(Math.floor((level+1)/3)){
switch (Math.floor((level + 1) / 3)) {
case 1:
return asNr ? 1 : 'tier1';
case 2:
@ -60,23 +59,26 @@ export const getTier = (level, asNr) => {
default:
return asNr ? 0 : 'tier0';
}
}
};
export const capitalize = (string) => {
export const capitalize = string => {
return string.charAt(0).toUpperCase() + string.slice(1);
}
};
export const getPathValue = (path, entity, numeric) => {
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;
};
export const generateId = (title, length) => {
const id = title.split(" ").map((w, i) => {
const p = w.slugify({replacement: "", strict: true});
const id = title
.split(' ')
.map((w, i) => {
const p = w.slugify({ replacement: '', strict: true });
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 {
constructor(){
constructor() {
super();
this.targetTemplate = {
@ -9,27 +9,37 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
minimizedSheets: [],
config: undefined,
targets: undefined
}
};
this.setupHooks();
}
addChatListeners = async (app, html, data) => {
html.querySelectorAll('.roll-damage-button').forEach(element => element.addEventListener('click', event => this.onRollDamage(event, data.message)));
html.querySelectorAll('.target-container').forEach(element => element.addEventListener('hover', hover(this.hoverTarget, this.unhoverTarget))); // ????
html.querySelectorAll('.roll-damage-button').forEach(element =>
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.querySelectorAll('.damage-button').forEach(element => element.addEventListener('click', this.onDamage));
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.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)));
}
html.querySelectorAll('.advantage').forEach(element =>
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());
}
close(options){
close(options) {
Hooks.off('renderChatMessageHTML', this.addChatListeners);
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);
};
hoverTarget = (event) => {
hoverTarget = event => {
event.stopPropagation();
const token = canvas.tokens.get(event.currentTarget.dataset.token);
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);
if (!token.controlled) token._onHoverIn(event, { hoverOutOthers: true });
};
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();
const damage = Number.parseInt(event.currentTarget.dataset.value);
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);
}
};
onHealing = async (event) => {
onHealing = async event => {
event.stopPropagation();
const healing = Number.parseInt(event.currentTarget.dataset.value);
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);
}
}
};
onToggleTargets = async (event) => {
onToggleTargets = async event => {
event.stopPropagation();
$($(event.currentTarget).parent()).find('.target-container').toggleClass('hidden');
};
hoverAdvantage = (event) => {
hoverAdvantage = event => {
$(event.currentTarget).siblings('.advantage').toggleClass('unused');
};
@ -88,16 +100,16 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
event.stopPropagation();
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).off('click');
}
};
abilityUseButton = async (event, message) => {
event.stopPropagation();
const action = message.system.actions[Number.parseInt(event.currentTarget.dataset.index)];
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 {
constructor(data, context) {
@ -7,68 +7,68 @@ export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.
Hooks.on(socketEvent.DhpFearUpdate, this.onFearUpdate);
}
get template(){
get template() {
return 'systems/daggerheart/templates/ui/combatTracker.hbs';
}
activateListeners(html) {
super.activateListeners(html);
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-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.down", this.decreaseResource.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-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.down', this.decreaseResource.bind(this));
}
async useActionToken(event){
async useActionToken(event) {
event.stopPropagation();
const combatant = event.currentTarget.dataset.combatant;
await game.combat.useActionToken(combatant);
}
async tradeActions(event){
if(event.currentTarget.classList.contains('disabled')) return;
async tradeActions(event) {
if (event.currentTarget.classList.contains('disabled')) return;
const currentFear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear);
const value = currentFear+1;
const value = currentFear + 1;
if(value <= 6){
Hooks.callAll(socketEvent.GMUpdate,GMUpdateEvent.UpdateFear, null, value);
if (value <= 6) {
Hooks.callAll(socketEvent.GMUpdate, GMUpdateEvent.UpdateFear, null, value);
await game.socket.emit(`system.${SYSTEM.id}`, {
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(){
if(event.currentTarget.classList.contains('disabled')) return;
async tradeFear() {
if (event.currentTarget.classList.contains('disabled')) return;
const currentFear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear);
const value = currentFear-1;
if(value >= 0){
Hooks.callAll(socketEvent.GMUpdate,GMUpdateEvent.UpdateFear, null, value);
const value = currentFear - 1;
if (value >= 0) {
Hooks.callAll(socketEvent.GMUpdate, GMUpdateEvent.UpdateFear, null, value);
await game.socket.emit(`system.${SYSTEM.id}`, {
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) {
if(event.currentTarget.dataset.type === 'action'){
await game.combat.update({ "system.actions": game.combat.system.actions+1 });
if (event.currentTarget.dataset.type === 'action') {
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 value = currentFear+1;
if(event.currentTarget.dataset.type === 'fear' && value <= 6){
Hooks.callAll(socketEvent.GMUpdate,GMUpdateEvent.UpdateFear, null, value);
const value = currentFear + 1;
if (event.currentTarget.dataset.type === 'fear' && value <= 6) {
Hooks.callAll(socketEvent.GMUpdate, GMUpdateEvent.UpdateFear, null, value);
await game.socket.emit(`system.${SYSTEM.id}`, {
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) {
if(event.currentTarget.dataset.type === 'action' && game.combat.system.actions-1 >= 0){
await game.combat.update({ "system.actions": game.combat.system.actions-1 });
if (event.currentTarget.dataset.type === 'action' && game.combat.system.actions - 1 >= 0) {
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 value = currentFear-1;
if(event.currentTarget.dataset.type === 'fear' && value >= 0){
Hooks.callAll(socketEvent.GMUpdate,GMUpdateEvent.UpdateFear, null, value);
const value = currentFear - 1;
if (event.currentTarget.dataset.type === 'fear' && value >= 0) {
Hooks.callAll(socketEvent.GMUpdate, GMUpdateEvent.UpdateFear, null, value);
await game.socket.emit(`system.${SYSTEM.id}`, {
action: socketEvent.GMUpdate,
data: { action: GMUpdateEvent.UpdateFear, update: value },
data: { action: GMUpdateEvent.UpdateFear, update: value }
});
}
this.render();
}
async getData(options={}) {
async getData(options = {}) {
let context = await super.getData(options);
// 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 combats = this.combats;
const currentIdx = combats.findIndex(c => c === combat);
const previousId = currentIdx > 0 ? 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 previousId = currentIdx > 0 ? 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);
// Prepare rendering data
context = foundry.utils.mergeObject(context, {
@ -121,17 +121,18 @@ export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.
linked: combat?.scene !== null,
labels: {}
});
context.labels.scope = game.i18n.localize(`COMBAT.${context.linked ? "Linked" : "Unlinked"}`);
if ( !hasCombat ) return context;
context.labels.scope = game.i18n.localize(`COMBAT.${context.linked ? 'Linked' : 'Unlinked'}`);
if (!hasCombat) return context;
// Format information about each combatant in the encounter
let hasDecimals = false;
const turns = [];
for ( let [i, combatant] of combat.turns.entries() ) {
if ( !combatant.visible ) continue;
for (let [i, combatant] of combat.turns.entries()) {
if (!combatant.visible) continue;
// 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 = {
id: combatant.id,
name: combatant.name,
@ -144,27 +145,25 @@ export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.
hasRolled: combatant.initiative !== null,
hasResource: resource !== null,
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,
ownedByPlayer: combatant.hasPlayerOwner,
ownedByPlayer: combatant.hasPlayerOwner
};
if ( (turn.initiative !== null) && !Number.isInteger(turn.initiative) ) hasDecimals = true;
turn.css = [
turn.active ? "active" : "",
turn.hidden ? "hidden" : "",
turn.defeated ? "defeated" : ""
].join(" ").trim();
if (turn.initiative !== null && !Number.isInteger(turn.initiative)) hasDecimals = true;
turn.css = [turn.active ? 'active' : '', turn.hidden ? 'hidden' : '', turn.defeated ? 'defeated' : '']
.join(' ')
.trim();
// Actor and Token status effects
turn.effects = new Set();
if ( combatant.token ) {
if (combatant.token) {
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 ) {
for ( const effect of combatant.actor.temporaryEffects ) {
if ( effect.statuses.has(CONFIG.specialStatusEffects.DEFEATED) ) turn.defeated = true;
else if ( effect.icon ) turn.effects.add(effect.icon);
if (combatant.actor) {
for (const effect of combatant.actor.temporaryEffects) {
if (effect.statuses.has(CONFIG.specialStatusEffects.DEFEATED)) turn.defeated = true;
else if (effect.icon) turn.effects.add(effect.icon);
}
}
turns.push(turn);
@ -173,7 +172,7 @@ export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.
// Format initiative numeric precision
const precision = CONFIG.Combat.initiative.decimals;
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);
@ -184,15 +183,15 @@ export default class DhpCombatTracker extends foundry.applications.sidebar.tabs.
turn: combat.turn,
turns: turns,
control: combat.combatant?.players?.includes(game.user),
fear: fear,
fear: fear
});
}
onFearUpdate = async () => {
this.render(true);
}
};
async close(options){
async close(options) {
Hooks.off(socketEvent.DhpFearUpdate, this.onFearUpdate);
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 {
constructor(data, context) {
@ -7,11 +7,11 @@ export default class DhpPlayers extends foundry.applications.ui.Players {
Hooks.on(socketEvent.DhpFearUpdate, this.onFearUpdate);
}
get template(){
get template() {
return 'systems/daggerheart/templates/ui/players.hbs';
}
async getData(options={}) {
async getData(options = {}) {
const context = super.getData(options);
context.fear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear);
context.user = game.user;
@ -21,31 +21,31 @@ export default class DhpPlayers extends foundry.applications.ui.Players {
activateListeners(html) {
// Toggle online/offline
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.down").click(async event => await this.updateFear(event, -1));
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.down').click(async event => await this.updateFear(event, -1));
// Context menu
const contextOptions = this._getUserContextOptions();
Hooks.call("getUserContextOptions", html, contextOptions);
new ContextMenu(html, ".player", contextOptions);
Hooks.call('getUserContextOptions', html, 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 value = Math.max(Math.min(fear+change, 6), 0);
Hooks.callAll(socketEvent.GMUpdate,GMUpdateEvent.UpdateFear, null, value);
const value = Math.max(Math.min(fear + change, 6), 0);
Hooks.callAll(socketEvent.GMUpdate, GMUpdateEvent.UpdateFear, null, value);
await game.socket.emit(`system.${SYSTEM.id}`, {
action: socketEvent.GMUpdate,
data: { action: GMUpdateEvent.UpdateFear, update: value },
data: { action: GMUpdateEvent.UpdateFear, update: value }
});
}
onFearUpdate = async () => {
this.render(true);
}
};
async close(options){
async close(options) {
Hooks.off(socketEvent.DhpFearUpdate, this.onFearUpdate);
return super.close(options);

View file

@ -1,7 +1,7 @@
export default class DhpRuler extends foundry.canvas.interaction.Ruler {
_getSegmentLabel(segment, totalDistance) {
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 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)}]`;
}
#getRangeLabel(distance, settings){
if(distance <= settings.melee){
return game.i18n.localize("DAGGERHEART.Range.Melee.Name");
#getRangeLabel(distance, settings) {
if (distance <= settings.melee) {
return game.i18n.localize('DAGGERHEART.Range.Melee.Name');
}
if(distance <= settings.veryClose){
return game.i18n.localize("DAGGERHEART.Range.VeryClose.Name");
if (distance <= settings.veryClose) {
return game.i18n.localize('DAGGERHEART.Range.VeryClose.Name');
}
if(distance <= settings.close){
return game.i18n.localize("DAGGERHEART.Range.Close.Name");
if (distance <= settings.close) {
return game.i18n.localize('DAGGERHEART.Range.Close.Name');
}
if(distance <= settings.far){
return game.i18n.localize("DAGGERHEART.Range.Far.Name");
if (distance <= settings.far) {
return game.i18n.localize('DAGGERHEART.Range.Far.Name');
}
if(distance <= settings.veryFar){
return game.i18n.localize("DAGGERHEART.Range.VeryFar.Name");
if (distance <= settings.veryFar) {
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-node-resolve": "^15.2.3",
"concurrently": "^8.2.2",
"husky": "^9.1.5",
"lint-staged": "^15.2.10",
"postcss": "^8.4.32",
"prettier": "^3.5.3",
"rollup-plugin-postcss": "^4.0.2"
},
"lint-staged": {
"**/*": "prettier --write --ignore-unknown"
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -33,16 +33,8 @@
"suggestedSecondaryWeapon": null,
"suggestedArmor": null,
"characterDescription": {},
"backgroundQuestions": [
"",
"",
""
],
"connections": [
"",
"",
""
]
"backgroundQuestions": ["", "", ""],
"connections": ["", "", ""]
},
"multiclass": null,
"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;
}
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;
}
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;
}
@ -153,7 +156,8 @@ div.daggerheart.views.multiclass { // Shouldn't be needed, but DEFAULT_OPTIONS d
margin-right: 8px;
cursor: pointer;
&:hover, &.selected {
&:hover,
&.selected {
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 {
.disadvantage, .advantage {
.disadvantage,
.advantage {
border: 2px solid @secondaryAccent;
border-radius: 6px;
display: flex;
@ -297,7 +302,7 @@ div.daggerheart.views.multiclass { // Shouldn't be needed, but DEFAULT_OPTIONS d
align-items: center;
flex: 1;
.dice-inner-container{
.dice-inner-container {
position: relative;
display: flex;
align-items: center;
@ -391,11 +396,13 @@ div.daggerheart.views.multiclass { // Shouldn't be needed, but DEFAULT_OPTIONS d
font-size: 24px;
cursor: pointer;
&.selected:not(.disabled), &:hover:not(.disabled) {
&.selected:not(.disabled),
&:hover:not(.disabled) {
filter: drop-shadow(0 0 3px gold);
}
&.inactive, &.disabled {
&.inactive,
&.disabled {
cursor: initial;
opacity: 0.4;
}

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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