mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-11 11:15:21 +01:00
Adding Prettier
* Added prettier with automatic useage on pre-commit to avoid style breakage * Ran Prettier on the project
This commit is contained in:
parent
820c2df1f4
commit
b24cdcc9ed
136 changed files with 13929 additions and 12206 deletions
1
.husky/pre-commit
Normal file
1
.husky/pre-commit
Normal file
|
|
@ -0,0 +1 @@
|
|||
npx lint-staged
|
||||
5
.prettierignore
Normal file
5
.prettierignore
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
node_modules
|
||||
package-lock.json
|
||||
package.json
|
||||
.github
|
||||
*.hbs
|
||||
13
.prettierrc
Normal file
13
.prettierrc
Normal 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
|
||||
}
|
||||
25
README.md
25
README.md
|
|
@ -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: 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/
|
||||
|
|
|
|||
119
daggerheart.mjs
119
daggerheart.mjs
|
|
@ -17,11 +17,14 @@ Hooks.once('init', () => {
|
|||
game.system.api = {
|
||||
applications,
|
||||
models,
|
||||
documents,
|
||||
}
|
||||
|
||||
CONFIG.statusEffects = Object.values(SYSTEM.GENERAL.conditions).map(x => ({ ...x, name: game.i18n.localize(x.name) }));
|
||||
|
||||
documents
|
||||
};
|
||||
|
||||
CONFIG.statusEffects = Object.values(SYSTEM.GENERAL.conditions).map(x => ({
|
||||
...x,
|
||||
name: game.i18n.localize(x.name)
|
||||
}));
|
||||
|
||||
CONFIG.Item.documentClass = documents.DhpItem;
|
||||
CONFIG.Item.dataModels = {
|
||||
ancestry: models.DhpAncestry,
|
||||
|
|
@ -29,49 +32,49 @@ Hooks.once('init', () => {
|
|||
class: models.DhpClass,
|
||||
subclass: models.DhpSubclass,
|
||||
feature: models.DhpFeature,
|
||||
domainCard: models.DhpDomainCard,
|
||||
domainCard: models.DhpDomainCard,
|
||||
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'
|
||||
]);
|
||||
};
|
||||
};
|
||||
|
|
|
|||
23
gulpfile.js
23
gulpfile.js
|
|
@ -2,20 +2,15 @@
|
|||
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")
|
||||
);
|
||||
cb();
|
||||
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.watch('styles/**/*.less', gulp.series('less'));
|
||||
cb();
|
||||
})
|
||||
);
|
||||
'default',
|
||||
gulp.series('less', function (cb) {
|
||||
gulp.watch('styles/**/*.less', gulp.series('less'));
|
||||
cb();
|
||||
})
|
||||
);
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@
|
|||
"Fear": "Fear",
|
||||
"CriticalSuccess": "Critical Success",
|
||||
"Advantage": "Advantage",
|
||||
"Disadvantage": "Disadvantage",
|
||||
"Disadvantage": "Disadvantage",
|
||||
"OK": "OK",
|
||||
"Cancel": "Cancel",
|
||||
"Or": "Or",
|
||||
|
|
@ -472,7 +472,7 @@
|
|||
},
|
||||
"Timeslowing": {
|
||||
"Name": "Timeslowing",
|
||||
"Description": "On any incoming attacks, roll 1d4 and add its value to your Evasion score."
|
||||
"Description": "On any incoming attacks, roll 1d4 and add its value to your Evasion score."
|
||||
},
|
||||
"Truthseeking": {
|
||||
"Name": "Truthseeking",
|
||||
|
|
@ -819,7 +819,7 @@
|
|||
"Bags": "Bags",
|
||||
"Chests": "Chests"
|
||||
},
|
||||
"Health":{
|
||||
"Health": {
|
||||
"Title": "HIT POINTS & STRESS",
|
||||
"Minor": "Minor",
|
||||
"Major": "Major",
|
||||
|
|
@ -1064,4 +1064,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,4 +11,4 @@ export { default as DhpConsumable } from './sheets/consumable.mjs';
|
|||
export { default as DhpWeapon } from './sheets/weapon.mjs';
|
||||
export { default as DhpArmor } from './sheets/armor.mjs';
|
||||
export { default as DhpChatMessage } from './chatMessage.mjs';
|
||||
export { default as DhpEnvironment } from './sheets/environment.mjs';
|
||||
export { default as DhpEnvironment } from './sheets/environment.mjs';
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
|
||||
|
||||
export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||
|
||||
constructor(resolve){
|
||||
constructor(resolve) {
|
||||
super({});
|
||||
|
||||
|
||||
this.resolve = resolve;
|
||||
this.data = {
|
||||
ancestries: [],
|
||||
|
|
@ -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"
|
||||
width: 800,
|
||||
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) }))
|
||||
const ancestryFeatures = this.data.ancestries.flatMap(x =>
|
||||
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);
|
||||
}
|
||||
|
|
@ -125,7 +131,7 @@ export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(
|
|||
this.data.ancestryInfo.name = event.currentTarget.value;
|
||||
this.render(true);
|
||||
}
|
||||
|
||||
|
||||
setDescription(event) {
|
||||
this.data.ancestryInfo.description = event.currentTarget.value;
|
||||
this.render(true);
|
||||
|
|
@ -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){
|
||||
this.data.ancestryInfo.customImg = path;
|
||||
this.data.ancestryInfo.img = path;
|
||||
this.render(true);
|
||||
_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() });
|
||||
}
|
||||
|
|
@ -170,7 +191,7 @@ export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(
|
|||
// export default class DamageSelectionDialog extends FormApplication {
|
||||
// constructor(rollString, bonusDamage, resolve){
|
||||
// super({}, {});
|
||||
|
||||
|
||||
// this.data = {
|
||||
// rollString,
|
||||
// bonusDamage: bonusDamage.map(x => ({
|
||||
|
|
@ -180,11 +201,11 @@ export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(
|
|||
// }
|
||||
// this.resolve = resolve;
|
||||
// }
|
||||
|
||||
|
||||
// get title (){
|
||||
// return 'Damage Options';
|
||||
// }
|
||||
|
||||
|
||||
// static get defaultOptions() {
|
||||
// const defaults = super.defaultOptions;
|
||||
// const overrides = {
|
||||
|
|
@ -195,35 +216,35 @@ export default class AncestrySelectionDialog extends HandlebarsApplicationMixin(
|
|||
// closeOnSubmit: false,
|
||||
// classes: ["daggerheart", "views", "damage-selection"],
|
||||
// };
|
||||
|
||||
|
||||
// const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
|
||||
|
||||
|
||||
// return mergedOptions;
|
||||
// }
|
||||
|
||||
|
||||
// async getData(){
|
||||
// const context = super.getData();
|
||||
// context.rollString = this.data.rollString;
|
||||
// context.bonusDamage = this.data.bonusDamage;
|
||||
|
||||
|
||||
// return context;
|
||||
// }
|
||||
|
||||
|
||||
// activateListeners(html) {
|
||||
// super.activateListeners(html);
|
||||
|
||||
|
||||
// html.find('.roll-button').click(this.finish.bind(this));
|
||||
// html.find('.').change();
|
||||
// }
|
||||
|
||||
|
||||
// // async _updateObject(_, formData) {
|
||||
// // const data = foundry.utils.expandObject(formData);
|
||||
// // this.data = foundry.utils.mergeObject(this.data, data);
|
||||
// // this.render(true);
|
||||
// // }
|
||||
|
||||
|
||||
// finish(){
|
||||
// this.resolve(this.data);
|
||||
// this.close();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
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);
|
||||
}
|
||||
|
||||
return super.renderHTML();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -10,40 +10,47 @@ export default class DaggerheartActionConfig extends DaggerheartSheet(Applicatio
|
|||
}
|
||||
|
||||
// get title(){
|
||||
// return `Action - ${this.action.name}`;
|
||||
// return `Action - ${this.action.name}`;
|
||||
// }
|
||||
|
||||
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;
|
||||
|
|
@ -61,14 +68,14 @@ export default class DaggerheartActionConfig extends DaggerheartSheet(Applicatio
|
|||
this.openSection = button.dataset.section === this.openSection ? null : button.dataset.section;
|
||||
this.render(true);
|
||||
}
|
||||
|
||||
|
||||
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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
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
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/** @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,17 +32,17 @@ 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) {
|
||||
event.preventDefault();
|
||||
const button = event.currentTarget;
|
||||
const action = button.dataset.action;
|
||||
|
||||
return this._handleAction(action, event, button);
|
||||
event.preventDefault();
|
||||
const button = event.currentTarget;
|
||||
const action = button.dataset.action;
|
||||
|
||||
return this._handleAction(action, event, button);
|
||||
}
|
||||
|
||||
async _handleAction(action, event, button) {}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
width: 400,
|
||||
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;
|
||||
const baseDamage = x.value;
|
||||
return acc.concat(` + ${nr}${baseDamage}`);
|
||||
}
|
||||
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;
|
||||
}, ""));
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
@ -121,7 +126,7 @@ export default class DamageSelectionDialog extends HandlebarsApplicationMixin(Ap
|
|||
// export default class DamageSelectionDialog extends FormApplication {
|
||||
// constructor(rollString, bonusDamage, resolve){
|
||||
// super({}, {});
|
||||
|
||||
|
||||
// this.data = {
|
||||
// rollString,
|
||||
// bonusDamage: bonusDamage.map(x => ({
|
||||
|
|
@ -131,11 +136,11 @@ export default class DamageSelectionDialog extends HandlebarsApplicationMixin(Ap
|
|||
// }
|
||||
// this.resolve = resolve;
|
||||
// }
|
||||
|
||||
|
||||
// get title (){
|
||||
// return 'Damage Options';
|
||||
// }
|
||||
|
||||
|
||||
// static get defaultOptions() {
|
||||
// const defaults = super.defaultOptions;
|
||||
// const overrides = {
|
||||
|
|
@ -146,35 +151,35 @@ export default class DamageSelectionDialog extends HandlebarsApplicationMixin(Ap
|
|||
// closeOnSubmit: false,
|
||||
// classes: ["daggerheart", "views", "damage-selection"],
|
||||
// };
|
||||
|
||||
|
||||
// const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
|
||||
|
||||
|
||||
// return mergedOptions;
|
||||
// }
|
||||
|
||||
|
||||
// async getData(){
|
||||
// const context = super.getData();
|
||||
// context.rollString = this.data.rollString;
|
||||
// context.bonusDamage = this.data.bonusDamage;
|
||||
|
||||
|
||||
// return context;
|
||||
// }
|
||||
|
||||
|
||||
// activateListeners(html) {
|
||||
// super.activateListeners(html);
|
||||
|
||||
|
||||
// html.find('.roll-button').click(this.finish.bind(this));
|
||||
// html.find('.').change();
|
||||
// }
|
||||
|
||||
|
||||
// // async _updateObject(_, formData) {
|
||||
// // const data = foundry.utils.expandObject(formData);
|
||||
// // this.data = foundry.utils.mergeObject(this.data, data);
|
||||
// // this.render(true);
|
||||
// // }
|
||||
|
||||
|
||||
// finish(){
|
||||
// this.resolve(this.data);
|
||||
// this.close();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -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,28 +36,27 @@ 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", {
|
||||
player: game.user.character.name,
|
||||
title: game.i18n.localize(this.selectedMove.name),
|
||||
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());
|
||||
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,44 +39,53 @@ 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", {
|
||||
player: game.user.character.name,
|
||||
title: game.i18n.localize(this.selectedActivity.name),
|
||||
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());
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,77 +1,82 @@
|
|||
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(){
|
||||
return `${this.actor.name} - Level Up`;
|
||||
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) => {
|
||||
const levelData = this.data.levelups[levelKey];
|
||||
['tier1','tier2','tier3'].forEach(tierKey => {
|
||||
let tierUpdate = {};
|
||||
const tierData = levelData[tierKey];
|
||||
if(tierData){
|
||||
tierUpdate = Object.keys(tierData).reduce((acc, propertyKey) => {
|
||||
const values = tierData[propertyKey];
|
||||
const level = Number.parseInt(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 => {
|
||||
let tierUpdate = {};
|
||||
const tierData = levelData[tierKey];
|
||||
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;
|
||||
|
||||
return { level: level, value: value };
|
||||
});
|
||||
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;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
Object.keys(tierUpdate).forEach(propertyKey => {
|
||||
const property = tierUpdate[propertyKey];
|
||||
const propertyValues = foundry.utils.getProperty(acc, `${tierKey}.${propertyKey}`)??[];
|
||||
foundry.utils.setProperty(acc, `${tierKey}.${propertyKey}`, [...propertyValues, ...property]);
|
||||
return { level: level, value: value };
|
||||
});
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
Object.keys(tierUpdate).forEach(propertyKey => {
|
||||
const property = tierUpdate[propertyKey];
|
||||
const propertyValues = foundry.utils.getProperty(acc, `${tierKey}.${propertyKey}`) ?? [];
|
||||
foundry.utils.setProperty(acc, `${tierKey}.${propertyKey}`, [...propertyValues, ...property]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return acc;
|
||||
}, { tier1: {}, tier2: {}, tier3: {} });
|
||||
return acc;
|
||||
},
|
||||
{ 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' };
|
||||
}
|
||||
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) {
|
||||
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
|
||||
}
|
||||
];
|
||||
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 } } };
|
||||
}
|
||||
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) {
|
||||
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
|
||||
}
|
||||
}
|
||||
};
|
||||
} 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: {
|
||||
levelData: this.data,
|
||||
experiences: [...this.actor.system.experiences, ...experiences],
|
||||
}}, { diff: false });
|
||||
await this.actor.update(
|
||||
{
|
||||
system: {
|
||||
levelData: this.data,
|
||||
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);
|
||||
|
|
@ -243,17 +327,21 @@ export default class DhpLevelup extends HandlebarsApplicationMixin(ApplicationV2
|
|||
|
||||
const multiclassSubclass = (await fromUuid(multiclass.subclass.uuid)).toObject();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,58 +1,60 @@
|
|||
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){
|
||||
acc.add(x);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, new Set()));
|
||||
this.classChoices = Array.from(
|
||||
game.items.reduce((acc, x) => {
|
||||
if (x.type === 'class' && x.name !== actorClass.name) {
|
||||
acc.add(x);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, new Set())
|
||||
);
|
||||
this.subclassChoices = [];
|
||||
this.domainChoices = [];
|
||||
|
||||
this.data = {
|
||||
class: null,
|
||||
subclass: null,
|
||||
domain: null,
|
||||
domain: null
|
||||
};
|
||||
}
|
||||
|
||||
get title(){
|
||||
return `${this.actorName} - Multiclass`;
|
||||
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);
|
||||
context.classChoices = this.classChoices;
|
||||
context.subclassChoices = this.subclassChoices;
|
||||
context.domainChoices = this.domainChoices;
|
||||
context.disabledFinish = !this.data.class || !this.data.subclass || !this.data.domain;
|
||||
context.disabledFinish = !this.data.class || !this.data.subclass || !this.data.domain;
|
||||
context.data = this.data;
|
||||
|
||||
return context;
|
||||
|
|
@ -61,38 +63,51 @@ 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 => {
|
||||
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) };
|
||||
}) : [];
|
||||
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)
|
||||
};
|
||||
})
|
||||
: [];
|
||||
}
|
||||
|
||||
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.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,76 +1,81 @@
|
|||
export default class NpcRollSelectionDialog extends FormApplication {
|
||||
constructor(experiences, resolve, isNpc){
|
||||
super({}, {});
|
||||
constructor(experiences, resolve, isNpc) {
|
||||
super({}, {});
|
||||
|
||||
this.experiences = experiences;
|
||||
this.resolve = resolve;
|
||||
this.selectedExperiences = [];
|
||||
this.data = {
|
||||
nrDice: 1,
|
||||
advantage: null,
|
||||
};
|
||||
}
|
||||
this.experiences = experiences;
|
||||
this.resolve = resolve;
|
||||
this.selectedExperiences = [];
|
||||
this.data = {
|
||||
nrDice: 1,
|
||||
advantage: null
|
||||
};
|
||||
}
|
||||
|
||||
get title (){
|
||||
return 'Roll Options';
|
||||
}
|
||||
get title() {
|
||||
return 'Roll Options';
|
||||
}
|
||||
|
||||
static get defaultOptions() {
|
||||
const defaults = super.defaultOptions;
|
||||
const overrides = {
|
||||
height: 'auto',
|
||||
width: 400,
|
||||
id: 'roll-selection',
|
||||
template: 'systems/daggerheart/templates/views/npcRollSelection.hbs',
|
||||
closeOnSubmit: false,
|
||||
submitOnChange: true,
|
||||
classes: ["daggerheart", "views", "npc-roll-selection"],
|
||||
};
|
||||
|
||||
const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
|
||||
|
||||
return mergedOptions;
|
||||
}
|
||||
|
||||
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) }));
|
||||
static get defaultOptions() {
|
||||
const defaults = super.defaultOptions;
|
||||
const overrides = {
|
||||
height: 'auto',
|
||||
width: 400,
|
||||
id: 'roll-selection',
|
||||
template: 'systems/daggerheart/templates/views/npcRollSelection.hbs',
|
||||
closeOnSubmit: false,
|
||||
submitOnChange: true,
|
||||
classes: ['daggerheart', 'views', 'npc-roll-selection']
|
||||
};
|
||||
|
||||
return context;
|
||||
}
|
||||
const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
|
||||
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
return mergedOptions;
|
||||
}
|
||||
|
||||
html.find('.increase').click(_ => this.updateNrDice(1));
|
||||
html.find('.decrease').click(_ => this.updateNrDice(-1));
|
||||
html.find('.advantage').click(_ => this.updateIsAdvantage(true));
|
||||
html.find('.disadvantage').click(_ => this.updateIsAdvantage(false));
|
||||
html.find('.roll-button').click(this.finish.bind(this));
|
||||
html.find('.roll-dialog-chip').click(this.selectExperience.bind(this));
|
||||
}
|
||||
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)
|
||||
}));
|
||||
|
||||
updateNrDice(value){
|
||||
this.data.nrDice += value;
|
||||
this.render();
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
updateIsAdvantage(advantage) {
|
||||
this.data.advantage = this.data.advantage === advantage ? null : advantage;
|
||||
this.render();
|
||||
}
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
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];
|
||||
html.find('.increase').click(_ => this.updateNrDice(1));
|
||||
html.find('.decrease').click(_ => this.updateNrDice(-1));
|
||||
html.find('.advantage').click(_ => this.updateIsAdvantage(true));
|
||||
html.find('.disadvantage').click(_ => this.updateIsAdvantage(false));
|
||||
html.find('.roll-button').click(this.finish.bind(this));
|
||||
html.find('.roll-dialog-chip').click(this.selectExperience.bind(this));
|
||||
}
|
||||
|
||||
this.render();
|
||||
}
|
||||
updateNrDice(value) {
|
||||
this.data.nrDice += value;
|
||||
this.render();
|
||||
}
|
||||
|
||||
finish(){
|
||||
this.resolve({ ...this.data, experiences: this.selectedExperiences });
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
updateIsAdvantage(advantage) {
|
||||
this.data.advantage = this.data.advantage === advantage ? null : advantage;
|
||||
this.render();
|
||||
}
|
||||
|
||||
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.render();
|
||||
}
|
||||
|
||||
finish() {
|
||||
this.resolve({ ...this.data, experiences: this.selectedExperiences });
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,147 +1,161 @@
|
|||
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
|
||||
|
||||
export default class RollSelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||
constructor(experiences, bonusDamage, hopeResource, resolve, isNpc){
|
||||
super({}, {});
|
||||
constructor(experiences, bonusDamage, hopeResource, resolve, isNpc) {
|
||||
super({}, {});
|
||||
|
||||
this.experiences = experiences;
|
||||
this.resolve = resolve;
|
||||
this.isNpc;
|
||||
this.selectedExperiences = [];
|
||||
this.data = {
|
||||
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(({
|
||||
...x,
|
||||
hopeUses: 0
|
||||
}));
|
||||
this.experiences = experiences;
|
||||
this.resolve = resolve;
|
||||
this.isNpc;
|
||||
this.selectedExperiences = [];
|
||||
this.data = {
|
||||
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({
|
||||
...x,
|
||||
hopeUses: 0
|
||||
});
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []),
|
||||
hopeResource: hopeResource
|
||||
};
|
||||
}
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
classes: ['daggerheart', 'views', 'roll-selection'],
|
||||
position: {
|
||||
width: 400,
|
||||
height: 'auto'
|
||||
},
|
||||
actions: {
|
||||
selectExperience: this.selectExperience,
|
||||
decreaseHopeUse: this.decreaseHopeUse,
|
||||
increaseHopeUse: this.increaseHopeUse,
|
||||
setAdvantage: this.setAdvantage,
|
||||
setDisadvantage: this.setDisadvantage,
|
||||
finish: this.finish
|
||||
},
|
||||
form: {
|
||||
handler: this.updateSelection,
|
||||
submitOnChange: true,
|
||||
submitOnClose: false
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []),
|
||||
hopeResource: hopeResource,
|
||||
};
|
||||
}
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
classes: ["daggerheart", "views", "roll-selection"],
|
||||
position: {
|
||||
width: 400,
|
||||
height: "auto"
|
||||
},
|
||||
actions: {
|
||||
selectExperience: this.selectExperience,
|
||||
decreaseHopeUse: this.decreaseHopeUse,
|
||||
increaseHopeUse: this.increaseHopeUse,
|
||||
setAdvantage: this.setAdvantage,
|
||||
setDisadvantage: this.setDisadvantage,
|
||||
finish: this.finish,
|
||||
},
|
||||
form: {
|
||||
handler: this.updateSelection,
|
||||
submitOnChange: true,
|
||||
submitOnClose: false,
|
||||
}
|
||||
};
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
damageSelection: {
|
||||
id: "damageSelection",
|
||||
template: "systems/daggerheart/templates/views/rollSelection.hbs"
|
||||
}
|
||||
}
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
damageSelection: {
|
||||
id: 'damageSelection',
|
||||
template: 'systems/daggerheart/templates/views/rollSelection.hbs'
|
||||
}
|
||||
};
|
||||
|
||||
get title() {
|
||||
return `Roll Options`;
|
||||
}
|
||||
get title() {
|
||||
return `Roll Options`;
|
||||
}
|
||||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
context.isNpc = this.isNpc;
|
||||
context.diceOptions = this.data.diceOptions;
|
||||
context.hope = this.data.hope;
|
||||
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.bonusDamage = this.data.bonusDamage;
|
||||
context.hopeResource = this.data.hopeResource+1;
|
||||
context.hopeUsed = this.getHopeUsed();
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
context.isNpc = this.isNpc;
|
||||
context.diceOptions = this.data.diceOptions;
|
||||
context.hope = this.data.hope;
|
||||
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.bonusDamage = this.data.bonusDamage;
|
||||
context.hopeResource = this.data.hopeResource + 1;
|
||||
context.hopeUsed = this.getHopeUsed();
|
||||
|
||||
return context;
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
static updateSelection(event, _, formData){
|
||||
const { bonusDamage, ...rest } = foundry.utils.expandObject(formData.object);
|
||||
|
||||
for(var index in bonusDamage){
|
||||
this.data.bonusDamage[index].initiallySelected = bonusDamage[index].initiallySelected;
|
||||
if(bonusDamage[index].hopeUses){
|
||||
const value = Number.parseInt(bonusDamage[index].hopeUses);
|
||||
if(!Number.isNaN(value)) this.data.bonusDamage[index].hopeUses = value;
|
||||
static updateSelection(event, _, formData) {
|
||||
const { bonusDamage, ...rest } = foundry.utils.expandObject(formData.object);
|
||||
|
||||
for (var index in bonusDamage) {
|
||||
this.data.bonusDamage[index].initiallySelected = bonusDamage[index].initiallySelected;
|
||||
if (bonusDamage[index].hopeUses) {
|
||||
const value = Number.parseInt(bonusDamage[index].hopeUses);
|
||||
if (!Number.isNaN(value)) this.data.bonusDamage[index].hopeUses = value;
|
||||
}
|
||||
}
|
||||
|
||||
this.data = foundry.utils.mergeObject(this.data, rest);
|
||||
this.render();
|
||||
}
|
||||
|
||||
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.render();
|
||||
}
|
||||
|
||||
getHopeUsed() {
|
||||
return this.data.bonusDamage.reduce((acc, x) => acc + x.hopeUses, 0);
|
||||
}
|
||||
|
||||
static decreaseHopeUse(_, button) {
|
||||
const index = Number.parseInt(button.dataset.index);
|
||||
if (this.data.bonusDamage[index].hopeUses - 1 >= 0) {
|
||||
this.data.bonusDamage[index].hopeUses -= 1;
|
||||
this.render(true);
|
||||
}
|
||||
}
|
||||
|
||||
this.data = foundry.utils.mergeObject(this.data, rest);
|
||||
this.render();
|
||||
}
|
||||
|
||||
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)];
|
||||
static increaseHopeUse(_, button) {
|
||||
const index = Number.parseInt(button.dataset.index);
|
||||
if (this.data.bonusDamage[index].hopeUses <= this.data.hopeResource + 1) {
|
||||
this.data.bonusDamage[index].hopeUses += 1;
|
||||
this.render(true);
|
||||
}
|
||||
}
|
||||
|
||||
this.render();
|
||||
}
|
||||
static setAdvantage() {
|
||||
this.data.advantage = this.data.advantage ? null : 'd6';
|
||||
this.data.disadvantage = null;
|
||||
|
||||
getHopeUsed(){
|
||||
return this.data.bonusDamage.reduce((acc, x) => acc+x.hopeUses, 0);
|
||||
}
|
||||
this.render(true);
|
||||
}
|
||||
|
||||
static decreaseHopeUse(_, button){
|
||||
const index = Number.parseInt(button.dataset.index);
|
||||
if(this.data.bonusDamage[index].hopeUses - 1 >= 0) {
|
||||
this.data.bonusDamage[index].hopeUses -= 1;
|
||||
this.render(true);
|
||||
}
|
||||
}
|
||||
static setDisadvantage() {
|
||||
this.data.advantage = null;
|
||||
this.data.disadvantage = this.data.disadvantage ? null : 'd6';
|
||||
|
||||
static increaseHopeUse(_, button){
|
||||
const index = Number.parseInt(button.dataset.index);
|
||||
if(this.data.bonusDamage[index].hopeUses <= this.data.hopeResource+1) {
|
||||
this.data.bonusDamage[index].hopeUses += 1;
|
||||
this.render(true);
|
||||
}
|
||||
}
|
||||
this.render(true);
|
||||
}
|
||||
|
||||
static setAdvantage(){
|
||||
this.data.advantage = this.data.advantage ? null : 'd6';
|
||||
this.data.disadvantage = null;
|
||||
|
||||
this.render(true);
|
||||
}
|
||||
|
||||
static setDisadvantage(){
|
||||
this.data.advantage = null;
|
||||
this.data.disadvantage = this.data.disadvantage ? null : 'd6';
|
||||
|
||||
this.render(true);
|
||||
}
|
||||
|
||||
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.close();
|
||||
}
|
||||
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.close();
|
||||
}
|
||||
}
|
||||
|
||||
// V1.3
|
||||
|
|
@ -194,7 +208,7 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
|
|||
// closeOnSubmit: false,
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
// /** @override */
|
||||
// static PARTS = {
|
||||
// damageSelection: {
|
||||
|
|
@ -225,7 +239,7 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
|
|||
|
||||
// static updateSelection(event, _, formData){
|
||||
// const { bonusDamage, ...rest } = foundry.utils.expandObject(formData.object);
|
||||
|
||||
|
||||
// for(var index in bonusDamage){
|
||||
// this.data.bonusDamage[index].initiallySelected = bonusDamage[index].initiallySelected;
|
||||
// if(bonusDamage[index].hopeUses){
|
||||
|
|
@ -273,4 +287,4 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
|
|||
// 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();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
class DhpAutomationSettings extends FormApplication {
|
||||
constructor(object={}, options={}){
|
||||
constructor(object = {}, options = {}) {
|
||||
super(object, options);
|
||||
}
|
||||
|
||||
static get defaultOptions() {
|
||||
const defaults = super.defaultOptions;
|
||||
const overrides = {
|
||||
height: 'auto',
|
||||
width: 400,
|
||||
id: 'daggerheart-automation-settings',
|
||||
template: 'systems/daggerheart/templates/views/automation-settings.hbs',
|
||||
closeOnSubmit: true,
|
||||
submitOnChange: false,
|
||||
classes: ["daggerheart", "views", "settings"],
|
||||
height: 'auto',
|
||||
width: 400,
|
||||
id: 'daggerheart-automation-settings',
|
||||
template: 'systems/daggerheart/templates/views/automation-settings.hbs',
|
||||
closeOnSubmit: true,
|
||||
submitOnChange: false,
|
||||
classes: ['daggerheart', 'views', 'settings']
|
||||
};
|
||||
|
||||
|
||||
const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
|
||||
|
||||
|
||||
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,35 +36,35 @@ 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);
|
||||
}
|
||||
|
||||
static get defaultOptions() {
|
||||
const defaults = super.defaultOptions;
|
||||
const overrides = {
|
||||
height: 'auto',
|
||||
width: 400,
|
||||
id: 'daggerheart-homebrew-settings',
|
||||
template: 'systems/daggerheart/templates/views/homebrew-settings.hbs',
|
||||
closeOnSubmit: true,
|
||||
submitOnChange: false,
|
||||
classes: ["daggerheart", "views", "settings"],
|
||||
height: 'auto',
|
||||
width: 400,
|
||||
id: 'daggerheart-homebrew-settings',
|
||||
template: 'systems/daggerheart/templates/views/homebrew-settings.hbs',
|
||||
closeOnSubmit: true,
|
||||
submitOnChange: false,
|
||||
classes: ['daggerheart', 'views', 'settings']
|
||||
};
|
||||
|
||||
|
||||
const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
|
||||
|
||||
|
||||
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);
|
||||
|
|
@ -95,25 +95,33 @@ class DhpRangeSettings extends FormApplication {
|
|||
static get defaultOptions() {
|
||||
const defaults = super.defaultOptions;
|
||||
const overrides = {
|
||||
height: 'auto',
|
||||
width: 400,
|
||||
id: 'daggerheart-range-settings',
|
||||
template: 'systems/daggerheart/templates/views/range-settings.hbs',
|
||||
closeOnSubmit: false,
|
||||
submitOnChange: true,
|
||||
classes: ["daggerheart", "views", "settings"],
|
||||
height: 'auto',
|
||||
width: 400,
|
||||
id: 'daggerheart-range-settings',
|
||||
template: 'systems/daggerheart/templates/views/range-settings.hbs',
|
||||
closeOnSubmit: false,
|
||||
submitOnChange: true,
|
||||
classes: ['daggerheart', 'views', 'settings']
|
||||
};
|
||||
|
||||
|
||||
const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
|
@ -246,7 +253,7 @@ export const registerDHPSettings = () => {
|
|||
// }
|
||||
|
||||
// get title(){
|
||||
// return game.i18n.localize("DAGGERHEART.Application.Settings.Title");
|
||||
// return game.i18n.localize("DAGGERHEART.Application.Settings.Title");
|
||||
// }
|
||||
|
||||
// static DEFAULT_OPTIONS = {
|
||||
|
|
@ -258,7 +265,7 @@ export const registerDHPSettings = () => {
|
|||
// },
|
||||
// form: { handler: this.updateData }
|
||||
// };
|
||||
|
||||
|
||||
// static PARTS = {
|
||||
// application: {
|
||||
// id: "settings",
|
||||
|
|
@ -279,4 +286,4 @@ export const registerDHPSettings = () => {
|
|||
// static close(){
|
||||
// super.close();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// import DhpApplicationMixin from '../daggerheart-sheet.mjs';
|
||||
|
||||
// export class Teest extends DhpApplicationMixin(ActorSheet) {
|
||||
|
|
@ -33,10 +32,10 @@
|
|||
// type: game.i18n.localize(SYSTEM.ACTOR.adversaryTypes[this.object.system.type].name),
|
||||
// attack: {
|
||||
// name: this.object.system.attack.name,
|
||||
// attackModifier: this.object.system.attackModifier,
|
||||
// attackModifier: this.object.system.attackModifier,
|
||||
// range: this.object.system.attack.range ? game.i18n.localize(SYSTEM.GENERAL.range[this.object.system.attack.range].name) : null,
|
||||
// damage: {
|
||||
// value: this.object.system.attack.damage.value,
|
||||
// value: this.object.system.attack.damage.value,
|
||||
// type: this.object.system.attack.damage.type,
|
||||
// typeName: this.object.system.attack.damage.type ? game.i18n.localize(SYSTEM.GENERAL.damageTypes[this.object.system.attack.damage.type].abbreviation).toLowerCase() : null,
|
||||
// },
|
||||
|
|
@ -68,7 +67,7 @@
|
|||
// case 'addMotive':
|
||||
// await this.addMotive();
|
||||
// break;
|
||||
// case 'removeMotive':
|
||||
// case 'removeMotive':
|
||||
// await this.removeMotive(button);
|
||||
// break;
|
||||
// case 'reactionRoll':
|
||||
|
|
@ -138,7 +137,7 @@
|
|||
// content: "systems/daggerheart/templates/chat/adversary-roll.hbs",
|
||||
// rolls: [roll]
|
||||
// });
|
||||
|
||||
|
||||
// cls.create(msg.toObject());
|
||||
// }
|
||||
|
||||
|
|
@ -169,7 +168,7 @@
|
|||
// content: "systems/daggerheart/templates/chat/adversary-attack-roll.hbs",
|
||||
// rolls: [roll]
|
||||
// });
|
||||
|
||||
|
||||
// cls.create(msg.toObject());
|
||||
// }
|
||||
|
||||
|
|
@ -198,16 +197,16 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
|
@ -251,93 +250,119 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
type: game.i18n.localize(SYSTEM.ACTOR.adversaryTypes[this.document.system.type].name),
|
||||
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,
|
||||
attackModifier: this.document.system.attackModifier,
|
||||
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,
|
||||
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", [{
|
||||
name: game.i18n.localize('DAGGERHEART.Sheets.Adversary.NewMove'),
|
||||
type: 'feature',
|
||||
}]);
|
||||
static async addMove() {
|
||||
const result = await this.document.createEmbeddedDocuments('Item', [
|
||||
{
|
||||
name: game.i18n.localize('DAGGERHEART.Sheets.Adversary.NewMove'),
|
||||
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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,13 +24,12 @@
|
|||
// return context;
|
||||
// }
|
||||
|
||||
|
||||
// async _handleAction(action, event, button) {
|
||||
// switch(action){
|
||||
// case 'editAbility':
|
||||
// this.editAbility(button);
|
||||
// break;
|
||||
// case 'deleteAbility':
|
||||
// case 'deleteAbility':
|
||||
// this.deleteAbility(event);
|
||||
// break;
|
||||
// }
|
||||
|
|
@ -59,30 +58,30 @@
|
|||
import DaggerheartSheet from './daggerheart-sheet.mjs';
|
||||
|
||||
const { ItemSheetV2 } = foundry.applications.sheets;
|
||||
export default class AncestrySheet extends DaggerheartSheet(ItemSheetV2) {
|
||||
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 }
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
// return context;
|
||||
// }
|
||||
|
||||
|
||||
// async _handleAction(action, event, button) {
|
||||
// switch(action){
|
||||
// }
|
||||
|
|
@ -29,26 +28,26 @@
|
|||
import DaggerheartSheet from './daggerheart-sheet.mjs';
|
||||
|
||||
const { ItemSheetV2 } = foundry.applications.sheets;
|
||||
export default class ArmorSheet extends DaggerheartSheet(ItemSheetV2) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,17 +40,17 @@
|
|||
// const domainTagify = new Tagify(domainInput, {
|
||||
// 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.name), src: domain.src, background: domain.background };
|
||||
// }),
|
||||
// maxTags: 2,
|
||||
// callbacks : { invalid: this.onAddTag },
|
||||
// callbacks : { invalid: this.onAddTag },
|
||||
// dropdown : {
|
||||
// mapValueTo: 'name',
|
||||
// searchKeys: ['name'],
|
||||
// enabled: 0,
|
||||
// maxItems: 20,
|
||||
// enabled: 0,
|
||||
// maxItems: 20,
|
||||
// closeOnSelect : true,
|
||||
// highlightFirst: false,
|
||||
// },
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
// spellcheck='false'
|
||||
// tabIndex="${this.settings.a11y.focusableTags ? 0 : -1}"
|
||||
// class="${this.settings.classNames.tag} ${tagData.class ? tagData.class : ""}"
|
||||
// ${this.getAttributes(tagData)}>
|
||||
// ${this.getAttributes(tagData)}>
|
||||
// <x class="${this.settings.classNames.tagX}" role='button' aria-label='remove tag'></x>
|
||||
// <div>
|
||||
// <span class="${this.settings.classNames.tagText}">${tagData[this.settings.tagTextProp] || tagData.value}</span>
|
||||
|
|
@ -70,16 +70,16 @@
|
|||
// </tag>`;
|
||||
// }}
|
||||
// });
|
||||
|
||||
|
||||
// domainTagify.on('change', this.onDomainSelect.bind(this));
|
||||
// }
|
||||
// }
|
||||
|
||||
// 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.object.update({ "system.domains": domains.map(x => x.value) });
|
||||
|
|
@ -170,7 +170,7 @@
|
|||
|
||||
// super._onDragStart(event);
|
||||
// }
|
||||
|
||||
|
||||
// async _onDrop(event) {
|
||||
// const data = TextEditor.getDragEventData(event);
|
||||
// const item = await fromUuid(data.uuid);
|
||||
|
|
@ -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') },
|
||||
}
|
||||
for ( const v of Object.values(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')
|
||||
}
|
||||
};
|
||||
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;
|
||||
|
|
@ -270,32 +283,38 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
|
|||
|
||||
_attachPartListeners(partId, htmlElement, options) {
|
||||
super._attachPartListeners(partId, htmlElement, options);
|
||||
|
||||
|
||||
const domainInput = htmlElement.querySelector('.domain-input');
|
||||
const domainTagify = new Tagify(domainInput, {
|
||||
tagTextProp: "name",
|
||||
enforceWhitelist: true,
|
||||
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 };
|
||||
}),
|
||||
maxTags: 2,
|
||||
callbacks : { invalid: this.onAddTag },
|
||||
dropdown : {
|
||||
mapValueTo: 'name',
|
||||
searchKeys: ['name'],
|
||||
enabled: 0,
|
||||
maxItems: 20,
|
||||
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)}"
|
||||
tagTextProp: 'name',
|
||||
enforceWhitelist: true,
|
||||
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
|
||||
};
|
||||
}),
|
||||
maxTags: 2,
|
||||
callbacks: { invalid: this.onAddTag },
|
||||
dropdown: {
|
||||
mapValueTo: 'name',
|
||||
searchKeys: ['name'],
|
||||
enabled: 0,
|
||||
maxItems: 20,
|
||||
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}"
|
||||
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,11 +322,12 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
|
|||
<img src="${tagData.src}"></i>
|
||||
</div>
|
||||
</tag>`;
|
||||
}}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
domainTagify.on('change', this.onDomainSelect.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
|
|
@ -319,101 +339,145 @@ 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 }] });
|
||||
}
|
||||
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(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 } });
|
||||
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 (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 }
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,13 +24,12 @@
|
|||
// return context;
|
||||
// }
|
||||
|
||||
|
||||
// async _handleAction(action, event, button) {
|
||||
// switch(action){
|
||||
// case 'editAbility':
|
||||
// this.editAbility(button);
|
||||
// break;
|
||||
// case 'deleteAbility':
|
||||
// case 'deleteAbility':
|
||||
// this.deleteAbility(event);
|
||||
// break;
|
||||
// }
|
||||
|
|
@ -59,30 +58,30 @@
|
|||
import DaggerheartSheet from './daggerheart-sheet.mjs';
|
||||
|
||||
const { ItemSheetV2 } = foundry.applications.sheets;
|
||||
export default class CommunitySheet extends DaggerheartSheet(ItemSheetV2) {
|
||||
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 }
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,25 +23,25 @@
|
|||
import DaggerheartSheet from './daggerheart-sheet.mjs';
|
||||
|
||||
const { ItemSheetV2 } = foundry.applications.sheets;
|
||||
export default class ConsumableSheet extends DaggerheartSheet(ItemSheetV2) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,73 +1,73 @@
|
|||
const { HandlebarsApplicationMixin } = foundry.applications.api;
|
||||
|
||||
export default function DhpApplicationMixin(Base) {
|
||||
return class DhpSheetV2 extends HandlebarsApplicationMixin(Base) {
|
||||
constructor(options={}){
|
||||
super(options);
|
||||
return class DhpSheetV2 extends HandlebarsApplicationMixin(Base) {
|
||||
constructor(options = {}) {
|
||||
super(options);
|
||||
|
||||
this._dragDrop = this._createDragDropHandlers();
|
||||
}
|
||||
this._dragDrop = this._createDragDropHandlers();
|
||||
}
|
||||
|
||||
_attachPartListeners(partId, htmlElement, options) {
|
||||
super._attachPartListeners(partId, htmlElement, options);
|
||||
_attachPartListeners(partId, htmlElement, options) {
|
||||
super._attachPartListeners(partId, htmlElement, options);
|
||||
|
||||
this._dragDrop.forEach(d => d.bind(htmlElement));
|
||||
}
|
||||
this._dragDrop.forEach(d => d.bind(htmlElement));
|
||||
}
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
position: {
|
||||
width: 480,
|
||||
height: "auto"
|
||||
},
|
||||
actions: {
|
||||
onEditImage: this._onEditImage
|
||||
},
|
||||
dragDrop: [],
|
||||
};
|
||||
|
||||
async _prepareContext(_options, objectPath='document') {
|
||||
const context = await super._prepareContext(_options);
|
||||
context.source = this[objectPath].toObject();
|
||||
context.fields = this[objectPath].schema.fields;
|
||||
context.systemFields = this[objectPath].system ? this[objectPath].system.schema.fields : {};
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static _onEditImage(event, target) {
|
||||
const attr = target.dataset.edit;
|
||||
const current = foundry.utils.getProperty(this.document, attr);
|
||||
const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {};
|
||||
const fp = new FilePicker({
|
||||
current,
|
||||
type: "image",
|
||||
redirectToRoot: img ? [img] : [],
|
||||
callback: async path => this._updateImage.bind(this)(path),
|
||||
top: this.position.top + 40,
|
||||
left: this.position.left + 10
|
||||
});
|
||||
return fp.browse();
|
||||
}
|
||||
|
||||
async _updateImage(path){
|
||||
await this.document.update({ "img": path });
|
||||
}
|
||||
|
||||
_createDragDropHandlers() {
|
||||
return this.options.dragDrop.map(d => {
|
||||
// d.permissions = {
|
||||
// dragstart: this._canDragStart.bind(this),
|
||||
// drop: this._canDragDrop.bind(this)
|
||||
// };
|
||||
d.callbacks = {
|
||||
// dragstart: this._onDragStart.bind(this),
|
||||
// dragover: this._onDragOver.bind(this),
|
||||
drop: this._onDrop.bind(this)
|
||||
static DEFAULT_OPTIONS = {
|
||||
position: {
|
||||
width: 480,
|
||||
height: 'auto'
|
||||
},
|
||||
actions: {
|
||||
onEditImage: this._onEditImage
|
||||
},
|
||||
dragDrop: []
|
||||
};
|
||||
return new foundry.applications.ux.DragDrop.implementation(d);
|
||||
});
|
||||
}
|
||||
|
||||
_onDrop(event) {}
|
||||
}
|
||||
}
|
||||
async _prepareContext(_options, objectPath = 'document') {
|
||||
const context = await super._prepareContext(_options);
|
||||
context.source = this[objectPath].toObject();
|
||||
context.fields = this[objectPath].schema.fields;
|
||||
context.systemFields = this[objectPath].system ? this[objectPath].system.schema.fields : {};
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static _onEditImage(event, target) {
|
||||
const attr = target.dataset.edit;
|
||||
const current = foundry.utils.getProperty(this.document, attr);
|
||||
const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {};
|
||||
const fp = new FilePicker({
|
||||
current,
|
||||
type: 'image',
|
||||
redirectToRoot: img ? [img] : [],
|
||||
callback: async path => this._updateImage.bind(this)(path),
|
||||
top: this.position.top + 40,
|
||||
left: this.position.left + 10
|
||||
});
|
||||
return fp.browse();
|
||||
}
|
||||
|
||||
async _updateImage(path) {
|
||||
await this.document.update({ img: path });
|
||||
}
|
||||
|
||||
_createDragDropHandlers() {
|
||||
return this.options.dragDrop.map(d => {
|
||||
// d.permissions = {
|
||||
// dragstart: this._canDragStart.bind(this),
|
||||
// drop: this._canDragDrop.bind(this)
|
||||
// };
|
||||
d.callbacks = {
|
||||
// dragstart: this._onDragStart.bind(this),
|
||||
// dragover: this._onDragOver.bind(this),
|
||||
drop: this._onDrop.bind(this)
|
||||
};
|
||||
return new foundry.applications.ux.DragDrop.implementation(d);
|
||||
});
|
||||
}
|
||||
|
||||
_onDrop(event) {}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
width: 600,
|
||||
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,
|
||||
handler: this._updateForm,
|
||||
closeOnSubmit: false,
|
||||
submitOnChange: true
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
form: {
|
||||
id: "form",
|
||||
template: "systems/daggerheart/templates/sheets/environment.hbs"
|
||||
id: 'form',
|
||||
template: 'systems/daggerheart/templates/sheets/environment.hbs'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
|
@ -49,81 +48,87 @@ export default class DhpEnvironment extends DaggerheartSheet(DocumentSheetV2) {
|
|||
|
||||
async _prepareContext(_options) {
|
||||
return {
|
||||
title: `${this.document.name} - ${game.i18n.localize(SYSTEM.ACTOR.adversaryTypes[this.document.system.type].name)}`,
|
||||
user: this.document,
|
||||
source: this.document.toObject(),
|
||||
fields: this.document.schema.fields,
|
||||
data: {
|
||||
type: game.i18n.localize(SYSTEM.ACTOR.adversaryTypes[this.document.system.type].name),
|
||||
features: this.document.items.reduce((acc, x) => {
|
||||
if(x.type === 'feature'){
|
||||
const feature = x.toObject();
|
||||
acc.push({
|
||||
...feature,
|
||||
system: {
|
||||
...feature.system,
|
||||
actionType: game.i18n.localize(SYSTEM.ITEM.actionTypes[feature.system.actionType].name)
|
||||
},
|
||||
uuid: x.uuid
|
||||
});
|
||||
}
|
||||
title: `${this.document.name} - ${game.i18n.localize(SYSTEM.ACTOR.adversaryTypes[this.document.system.type].name)}`,
|
||||
user: this.document,
|
||||
source: this.document.toObject(),
|
||||
fields: this.document.schema.fields,
|
||||
data: {
|
||||
type: game.i18n.localize(SYSTEM.ACTOR.adversaryTypes[this.document.system.type].name),
|
||||
features: this.document.items.reduce((acc, x) => {
|
||||
if (x.type === 'feature') {
|
||||
const feature = x.toObject();
|
||||
acc.push({
|
||||
...feature,
|
||||
system: {
|
||||
...feature.system,
|
||||
actionType: game.i18n.localize(SYSTEM.ITEM.actionTypes[feature.system.actionType].name)
|
||||
},
|
||||
uuid: x.uuid
|
||||
});
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []),
|
||||
},
|
||||
editMode: this.editMode,
|
||||
config: SYSTEM,
|
||||
}
|
||||
return acc;
|
||||
}, [])
|
||||
},
|
||||
editMode: this.editMode,
|
||||
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", [{
|
||||
name: game.i18n.localize('DAGGERHEART.Sheets.Environment.NewFeature'),
|
||||
type: 'feature',
|
||||
}]);
|
||||
static async addFeature() {
|
||||
const result = await this.document.createEmbeddedDocuments('Item', [
|
||||
{
|
||||
name: game.i18n.localize('DAGGERHEART.Sheets.Environment.NewFeature'),
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,47 +4,47 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
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,47 +69,53 @@ 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 = {
|
||||
const update = {
|
||||
[foundry.utils.randomID()]: {
|
||||
type: this.selectedEffectType,
|
||||
value: '',
|
||||
...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)
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -51,7 +51,7 @@
|
|||
// const feature = event.currentTarget.dataset.feature;
|
||||
// const newAbilities = this.item.system[`${feature}Feature`].abilities.filter(x => x.uuid !== event.currentTarget.dataset.ability);
|
||||
// const path = `system.${feature}Feature.abilities`;
|
||||
|
||||
|
||||
// await this.item.update({ [path]: newAbilities });
|
||||
// }
|
||||
|
||||
|
|
@ -79,46 +79,74 @@ 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') },
|
||||
}
|
||||
for ( const v of Object.values(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')
|
||||
}
|
||||
};
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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,39 +158,51 @@ 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 });
|
||||
}
|
||||
|
||||
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]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
// return context;
|
||||
// }
|
||||
|
||||
|
||||
// async _handleAction(action, event, button) {
|
||||
// switch(action){
|
||||
// }
|
||||
|
|
@ -30,25 +29,25 @@
|
|||
import DaggerheartSheet from './daggerheart-sheet.mjs';
|
||||
|
||||
const { ItemSheetV2 } = foundry.applications.sheets;
|
||||
export default class WeaponSheet extends DaggerheartSheet(ItemSheetV2) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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: ''
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@ export { default as DhpArmor } from './armor.mjs';
|
|||
export { default as DhpDualityRoll } from './dualityRoll.mjs';
|
||||
export { default as DhpAdversaryRoll } from './adversaryRoll.mjs';
|
||||
export { default as DhpAbilityUse } from './abilityUse.mjs';
|
||||
export { default as DhpEnvironment } from './environment.mjs';
|
||||
export { default as DhpEnvironment } from './environment.mjs';
|
||||
|
|
|
|||
|
|
@ -1,30 +1,32 @@
|
|||
export default class DhpAbilityUse extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
const fields = foundry.data.fields;
|
||||
|
||||
return {
|
||||
title: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
name: new fields.StringField({}),
|
||||
description: new fields.StringField({}),
|
||||
actions: new fields.ArrayField(new fields.SchemaField({
|
||||
name: new fields.StringField({}),
|
||||
damage: new fields.SchemaField({
|
||||
type: new fields.StringField({}),
|
||||
value: new fields.StringField({}),
|
||||
}),
|
||||
healing: new fields.SchemaField({
|
||||
type: new fields.StringField({}),
|
||||
value: new fields.StringField({}),
|
||||
}),
|
||||
cost: new fields.SchemaField({
|
||||
type: new fields.StringField({ nullable: true }),
|
||||
value: new fields.NumberField({ nullable: true }),
|
||||
}),
|
||||
target: new fields.SchemaField({
|
||||
type: new fields.StringField({}),
|
||||
}),
|
||||
})),
|
||||
}
|
||||
return {
|
||||
title: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
name: new fields.StringField({}),
|
||||
description: new fields.StringField({}),
|
||||
actions: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
name: new fields.StringField({}),
|
||||
damage: new fields.SchemaField({
|
||||
type: new fields.StringField({}),
|
||||
value: new fields.StringField({})
|
||||
}),
|
||||
healing: new fields.SchemaField({
|
||||
type: new fields.StringField({}),
|
||||
value: new fields.StringField({})
|
||||
}),
|
||||
cost: new fields.SchemaField({
|
||||
type: new fields.StringField({ nullable: true }),
|
||||
value: new fields.NumberField({ nullable: true })
|
||||
}),
|
||||
target: new fields.SchemaField({
|
||||
type: new fields.StringField({})
|
||||
})
|
||||
})
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,38 +1,43 @@
|
|||
export default class DaggerheartAction extends foundry.abstract.DataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
id: new fields.StringField({}),
|
||||
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({}),
|
||||
}),
|
||||
healing: new fields.SchemaField({
|
||||
type: new fields.StringField({ choices: SYSTEM.GENERAL.healingTypes, nullable: true, initial: null }),
|
||||
value: new fields.StringField(),
|
||||
}),
|
||||
conditions: new fields.ArrayField(new fields.SchemaField({
|
||||
name: new fields.StringField(),
|
||||
icon: 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 }),
|
||||
}),
|
||||
target: new fields.SchemaField({
|
||||
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 }),
|
||||
// }),
|
||||
}
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
id: new fields.StringField({}),
|
||||
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({})
|
||||
}),
|
||||
healing: new fields.SchemaField({
|
||||
type: new fields.StringField({ choices: SYSTEM.GENERAL.healingTypes, nullable: true, initial: null }),
|
||||
value: new fields.StringField()
|
||||
}),
|
||||
conditions: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
name: new fields.StringField(),
|
||||
icon: 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 })
|
||||
}),
|
||||
target: new fields.SchemaField({
|
||||
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 () => {
|
||||
console.log('Test Use');
|
||||
console.log('Test Use');
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,48 +1,54 @@
|
|||
import { MappingField } from "./fields.mjs";
|
||||
import { MappingField } from './fields.mjs';
|
||||
|
||||
export default class DhpAdversary extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
resources: new fields.SchemaField({
|
||||
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 }),
|
||||
}),
|
||||
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 }),
|
||||
}),
|
||||
}),
|
||||
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') }),
|
||||
description: new fields.StringField({}),
|
||||
motivesAndTactics: new fields.ArrayField(new fields.StringField({})),
|
||||
attackModifier: new fields.NumberField({ integer: true, nullabe: true, initial: null }),
|
||||
attack: new fields.SchemaField({
|
||||
name: new fields.StringField({}),
|
||||
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 }),
|
||||
})
|
||||
}),
|
||||
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 }),
|
||||
}),
|
||||
experiences: new fields.ArrayField(new fields.SchemaField({
|
||||
name: new fields.StringField({}),
|
||||
value: new fields.NumberField({ integer: true, nullable: true, initial: null }),
|
||||
})),
|
||||
}
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
resources: new fields.SchemaField({
|
||||
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 })
|
||||
}),
|
||||
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 })
|
||||
})
|
||||
}),
|
||||
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')
|
||||
}),
|
||||
description: new fields.StringField({}),
|
||||
motivesAndTactics: new fields.ArrayField(new fields.StringField({})),
|
||||
attackModifier: new fields.NumberField({ integer: true, nullabe: true, initial: null }),
|
||||
attack: new fields.SchemaField({
|
||||
name: new fields.StringField({}),
|
||||
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 })
|
||||
})
|
||||
}),
|
||||
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 })
|
||||
}),
|
||||
experiences: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
name: new fields.StringField({}),
|
||||
value: new fields.NumberField({ integer: true, nullable: true, initial: null })
|
||||
})
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
get moves(){
|
||||
return this.parent.items.filter(x => x.type === 'feature');
|
||||
get moves() {
|
||||
return this.parent.items.filter(x => x.type === 'feature');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,50 +1,59 @@
|
|||
export default class DhpAdversaryRoll extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
const fields = foundry.data.fields;
|
||||
|
||||
return {
|
||||
roll: new fields.StringField({}),
|
||||
total: new fields.NumberField({ integer: true }),
|
||||
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({
|
||||
value: new fields.NumberField({ integer: true }),
|
||||
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({
|
||||
value: new fields.StringField({}),
|
||||
type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false }),
|
||||
}, { nullable: true, initial: null })
|
||||
}
|
||||
return {
|
||||
roll: new fields.StringField({}),
|
||||
total: new fields.NumberField({ integer: true }),
|
||||
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({
|
||||
value: new fields.NumberField({ integer: true }),
|
||||
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(
|
||||
{
|
||||
value: new fields.StringField({}),
|
||||
type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false })
|
||||
},
|
||||
{ nullable: true, initial: null }
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
prepareDerivedData(){
|
||||
const diceKeys = Object.keys(this.diceResults);
|
||||
const highestIndex = 0;
|
||||
for(var index in diceKeys){
|
||||
const resultIndex = Number.parseInt(index);
|
||||
if(highestIndex === resultIndex) continue;
|
||||
prepareDerivedData() {
|
||||
const diceKeys = Object.keys(this.diceResults);
|
||||
const highestIndex = 0;
|
||||
for (var index in diceKeys) {
|
||||
const resultIndex = Number.parseInt(index);
|
||||
if (highestIndex === resultIndex) continue;
|
||||
|
||||
const current = this.diceResults[resultIndex];
|
||||
const highest = this.diceResults[highestIndex];
|
||||
const current = this.diceResults[resultIndex];
|
||||
const highest = this.diceResults[highestIndex];
|
||||
|
||||
if(current.value > highest.value) this.diceResults[highestIndex].discarded = true;
|
||||
else this.diceResults[resultIndex].discarded = true;
|
||||
}
|
||||
if (current.value > highest.value) this.diceResults[highestIndex].discarded = true;
|
||||
else this.diceResults[resultIndex].discarded = true;
|
||||
}
|
||||
|
||||
this.targets.forEach(target => {
|
||||
target.hit = target.difficulty ? this.total >= target.difficulty : this.total >= target.evasion;
|
||||
});
|
||||
this.targets.forEach(target => {
|
||||
target.hit = target.difficulty ? this.total >= target.difficulty : this.total >= target.evasion;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
description: new fields.HTMLField({}),
|
||||
abilities: featuresSchema()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,49 +1,47 @@
|
|||
export default class DhpArmor extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
baseScore: new fields.NumberField({ initial: 1, integer: true }),
|
||||
feature: new fields.StringField({
|
||||
choices: SYSTEM.ITEM.armorFeatures,
|
||||
integer: false,
|
||||
blank: true,
|
||||
}),
|
||||
marks: new fields.SchemaField({
|
||||
max: new fields.NumberField({ initial: 6, 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 }),
|
||||
}),
|
||||
description: new fields.HTMLField({}),
|
||||
};
|
||||
}
|
||||
|
||||
get featureInfo() {
|
||||
return this.feature
|
||||
? CONFIG.daggerheart.ITEM.armorFeatures[this.feature]
|
||||
: null;
|
||||
}
|
||||
|
||||
prepareDerivedData() {
|
||||
if (this.parent.parent) {
|
||||
this.applyLevels();
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
baseScore: new fields.NumberField({ initial: 1, integer: true }),
|
||||
feature: new fields.StringField({
|
||||
choices: SYSTEM.ITEM.armorFeatures,
|
||||
integer: false,
|
||||
blank: true
|
||||
}),
|
||||
marks: new fields.SchemaField({
|
||||
max: new fields.NumberField({ initial: 6, 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 })
|
||||
}),
|
||||
description: new fields.HTMLField({})
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Currently bugged as it double triggers. Should get fixed in an updated foundry version.
|
||||
applyLevels() {
|
||||
// let armorBonus = 0;
|
||||
// for(var level in this.parent.parent.system.levelData.levelups){
|
||||
// var levelData = this.parent.parent.system.levelData.levelups[level];
|
||||
// for(var tier in levelData){
|
||||
// var tierData = levelData[tier];
|
||||
// if(tierData){
|
||||
// armorBonus += Object.keys(tierData.armorOrEvasionSlot).filter(x => tierData.armorOrEvasionSlot[x] === 'armor').length;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// this.marks.max += armorBonus;
|
||||
}
|
||||
get featureInfo() {
|
||||
return this.feature ? CONFIG.daggerheart.ITEM.armorFeatures[this.feature] : null;
|
||||
}
|
||||
|
||||
prepareDerivedData() {
|
||||
if (this.parent.parent) {
|
||||
this.applyLevels();
|
||||
}
|
||||
}
|
||||
|
||||
// Currently bugged as it double triggers. Should get fixed in an updated foundry version.
|
||||
applyLevels() {
|
||||
// let armorBonus = 0;
|
||||
// for(var level in this.parent.parent.system.levelData.levelups){
|
||||
// var levelData = this.parent.parent.system.levelData.levelups[level];
|
||||
// for(var tier in levelData){
|
||||
// var tierData = levelData[tier];
|
||||
// if(tierData){
|
||||
// armorBonus += Object.keys(tierData.armorOrEvasionSlot).filter(x => tierData.armorOrEvasionSlot[x] === 'armor').length;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// this.marks.max += armorBonus;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,93 +1,117 @@
|
|||
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({
|
||||
name: new fields.StringField({}),
|
||||
img: 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 }),
|
||||
}),
|
||||
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({
|
||||
name: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
uuid: new fields.StringField({}),
|
||||
})),
|
||||
inventory: 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({
|
||||
name: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
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({
|
||||
title: new fields.StringField({}),
|
||||
description: new fields.StringField({})
|
||||
}, { initial: null, nullable: true }),
|
||||
}),
|
||||
characterGuide: new fields.SchemaField({
|
||||
suggestedTraits: new fields.SchemaField({
|
||||
agility: new fields.NumberField({ initial: 0, integer: true }),
|
||||
strength: new fields.NumberField({ initial: 0, integer: true }),
|
||||
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 }),
|
||||
}),
|
||||
suggestedPrimaryWeapon: new fields.SchemaField({
|
||||
name: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
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({
|
||||
name: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
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({}),
|
||||
}),
|
||||
backgroundQuestions: 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({}),
|
||||
}
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
domains: new fields.ArrayField(new fields.StringField({})),
|
||||
classItems: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
name: new fields.StringField({}),
|
||||
img: 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 })
|
||||
}),
|
||||
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({
|
||||
name: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
uuid: new fields.StringField({})
|
||||
})
|
||||
),
|
||||
inventory: 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({
|
||||
name: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
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(
|
||||
{
|
||||
title: new fields.StringField({}),
|
||||
description: new fields.StringField({})
|
||||
},
|
||||
{ initial: null, nullable: true }
|
||||
)
|
||||
}),
|
||||
characterGuide: new fields.SchemaField({
|
||||
suggestedTraits: new fields.SchemaField({
|
||||
agility: new fields.NumberField({ initial: 0, integer: true }),
|
||||
strength: new fields.NumberField({ initial: 0, integer: true }),
|
||||
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 })
|
||||
}),
|
||||
suggestedPrimaryWeapon: new fields.SchemaField(
|
||||
{
|
||||
name: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
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(
|
||||
{
|
||||
name: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
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({})
|
||||
}),
|
||||
backgroundQuestions: 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({})
|
||||
};
|
||||
}
|
||||
|
||||
get multiclassTier(){
|
||||
return getTier(this.multiclass, true);
|
||||
get multiclassTier() {
|
||||
return getTier(this.multiclass, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
export default class DhpCombat extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
actions: new fields.NumberField({ initial: 0, integer: true }),
|
||||
activeCombatant: new fields.StringField({}),
|
||||
}
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
actions: new fields.NumberField({ initial: 0, integer: true }),
|
||||
activeCombatant: new fields.StringField({})
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
export default class DhpCombatant extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
active: new fields.BooleanField({ initial: false })
|
||||
}
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
active: new fields.BooleanField({ initial: false })
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
description: new fields.HTMLField({}),
|
||||
abilities: featuresSchema()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
export default class DhpConsumable extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
description: new fields.HTMLField({}),
|
||||
quantity: new fields.NumberField({ initial: 1, integer: true }),
|
||||
consumeOnUse: new fields.BooleanField({ initial: false }),
|
||||
}
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
description: new fields.HTMLField({}),
|
||||
quantity: new fields.NumberField({ initial: 1, integer: true }),
|
||||
consumeOnUse: new fields.BooleanField({ initial: false })
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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: [] }),
|
||||
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: [] }),
|
||||
foundation: new fields.BooleanField({ initial: false }),
|
||||
effect: new fields.HTMLField({}),
|
||||
inVault: new fields.BooleanField({ initial: false }),
|
||||
actions: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartAction)),
|
||||
}
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
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: [] }
|
||||
),
|
||||
foundation: new fields.BooleanField({ initial: false }),
|
||||
effect: new fields.HTMLField({}),
|
||||
inVault: new fields.BooleanField({ initial: false }),
|
||||
actions: new fields.ArrayField(new fields.EmbeddedDataField(DaggerheartAction))
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,65 +1,83 @@
|
|||
const fields = foundry.data.fields;
|
||||
const diceField = () => new fields.SchemaField({
|
||||
dice: new fields.StringField({}),
|
||||
value: new fields.NumberField({ integer: true}),
|
||||
});
|
||||
const diceField = () =>
|
||||
new fields.SchemaField({
|
||||
dice: new fields.StringField({}),
|
||||
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({
|
||||
value: new fields.NumberField({ integer: true }),
|
||||
label: 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({
|
||||
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({
|
||||
value: new fields.StringField({}),
|
||||
type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false }),
|
||||
bonusDamage: new fields.ArrayField(new fields.SchemaField({
|
||||
value: new fields.StringField({}),
|
||||
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 }),
|
||||
description: new fields.StringField({}),
|
||||
hopeIncrease: new fields.StringField({ nullable: true })
|
||||
}), { nullable: true, initial: null })
|
||||
})
|
||||
}
|
||||
return {
|
||||
roll: new fields.StringField({}),
|
||||
modifiers: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
value: new fields.NumberField({ integer: true }),
|
||||
label: 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({
|
||||
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({
|
||||
value: new fields.StringField({}),
|
||||
type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false }),
|
||||
bonusDamage: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
value: new fields.StringField({}),
|
||||
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 }
|
||||
),
|
||||
description: new fields.StringField({}),
|
||||
hopeIncrease: new fields.StringField({ nullable: true })
|
||||
}),
|
||||
{ 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;
|
||||
return this.hope.value + this.fear.value + advantage + modifiers;
|
||||
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";
|
||||
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';
|
||||
|
||||
return game.i18n.localize(label);
|
||||
return game.i18n.localize(label);
|
||||
}
|
||||
|
||||
prepareDerivedData(){
|
||||
const total = this.total;
|
||||
prepareDerivedData() {
|
||||
const total = this.total;
|
||||
|
||||
this.targets.forEach(target => {
|
||||
target.hit = target.difficulty ? total >= target.difficulty : total >= target.evasion;
|
||||
});
|
||||
this.targets.forEach(target => {
|
||||
target.hit = target.difficulty ? total >= target.difficulty : total >= target.evasion;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +128,7 @@ export default class DhpDualityRoll extends foundry.abstract.TypeDataModel {
|
|||
|
||||
// get total() {
|
||||
// const modifiers = this.modifiers.reduce((acc, x) => acc+x.value, 0);
|
||||
// const regular = {
|
||||
// const regular = {
|
||||
// normal: this.disadvantage.value ? Math.min(this.disadvantage.value, this.hope.value) + this.fear.value + modifiers : this.hope.value + this.fear.value + modifiers,
|
||||
// alternate: this.advantage.value ? this.advantage.value + this.fear.value + modifiers : null,
|
||||
// };
|
||||
|
|
@ -126,7 +144,7 @@ export default class DhpDualityRoll extends foundry.abstract.TypeDataModel {
|
|||
// get totalLabel() {
|
||||
// if(this.advantage.value && this.advantageSelected === 0) return game.i18n.localize("DAGGERHEART.Chat.DualityRoll.AdvantageChooseTitle");
|
||||
|
||||
// const hope = !this.advantage.value || this.advantageSelected === 1 ? this.hope.value : this.advantage.value;
|
||||
// const hope = !this.advantage.value || this.advantageSelected === 1 ? this.hope.value : this.advantage.value;
|
||||
// const label = hope > this.fear.value ? "DAGGERHEART.General.Hope" : this.fear.value > hope ? "DAGGERHEART.General.Fear" : "DAGGERHEART.General.CriticalSuccess";
|
||||
|
||||
// return game.i18n.localize(label);
|
||||
|
|
@ -147,4 +165,4 @@ export default class DhpDualityRoll extends foundry.abstract.TypeDataModel {
|
|||
// target.hit = target.difficulty ? total.normal >= target.difficulty : total.normal >= target.evasion;
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,20 +1,22 @@
|
|||
export default class DhpEnvironment extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
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') }),
|
||||
description: new fields.StringField({}),
|
||||
toneAndFeel: new fields.StringField({}),
|
||||
difficulty: new fields.NumberField({ initial: 1, integer: true }),
|
||||
potentialAdversaries: new fields.StringField({}),
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
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')
|
||||
}),
|
||||
description: new fields.StringField({}),
|
||||
toneAndFeel: new fields.StringField({}),
|
||||
difficulty: new fields.NumberField({ initial: 1, integer: true }),
|
||||
potentialAdversaries: new fields.StringField({})
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
get features(){
|
||||
return this.parent.items.filter(x => x.type === 'feature');
|
||||
}
|
||||
}
|
||||
get features() {
|
||||
return this.parent.items.filter(x => x.type === 'feature');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,77 +1,106 @@
|
|||
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({}, {
|
||||
type: new fields.StringField({ choices: SYSTEM.ITEM.featureTypes }),
|
||||
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') }),
|
||||
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') }),
|
||||
max: new fields.NumberField({ initial: 1, integer: true }),
|
||||
numbers: new MappingField(new fields.SchemaField({
|
||||
value: new fields.NumberField({ integer: true }),
|
||||
used: new fields.BooleanField({ initial: false }),
|
||||
})),
|
||||
}),
|
||||
}),
|
||||
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 }),
|
||||
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({
|
||||
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({
|
||||
name: new fields.StringField({}),
|
||||
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 }),
|
||||
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)),
|
||||
});
|
||||
const fields = foundry.data.fields;
|
||||
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
|
||||
}),
|
||||
featureType: new fields.SchemaField({
|
||||
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')
|
||||
}),
|
||||
max: new fields.NumberField({ initial: 1, integer: true }),
|
||||
numbers: new MappingField(
|
||||
new fields.SchemaField({
|
||||
value: new fields.NumberField({ integer: true }),
|
||||
used: new fields.BooleanField({ initial: false })
|
||||
})
|
||||
)
|
||||
})
|
||||
}),
|
||||
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 }
|
||||
),
|
||||
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({
|
||||
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({
|
||||
name: new fields.StringField({}),
|
||||
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
|
||||
}),
|
||||
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))
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
get multiclassTier(){
|
||||
return getTier(this.multiclass);
|
||||
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);
|
||||
await this.parent.update(update);
|
||||
|
||||
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});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prepareDerivedData(){
|
||||
// if(this.featureType.type === SYSTEM.ITEM.valueTypes.dice.id){
|
||||
// this.featureType.numbers = ;
|
||||
// this.featureType.numbers = ;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,50 +1,50 @@
|
|||
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");
|
||||
}
|
||||
super(options);
|
||||
|
||||
/**
|
||||
* The embedded DataField definition which is contained in this field.
|
||||
* @type {DataField}
|
||||
*/
|
||||
this.model = model;
|
||||
if (!(model instanceof foundry.data.fields.DataField)) {
|
||||
throw new Error('MappingField must have a DataField as its contained element');
|
||||
}
|
||||
super(options);
|
||||
|
||||
/**
|
||||
* The embedded DataField definition which is contained in this field.
|
||||
* @type {DataField}
|
||||
*/
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
||||
/** @inheritdoc */
|
||||
static get _defaults() {
|
||||
return foundry.utils.mergeObject(super._defaults, {
|
||||
initialKeys: null,
|
||||
initialValue: null,
|
||||
initialKeysOnly: false
|
||||
});
|
||||
return foundry.utils.mergeObject(super._defaults, {
|
||||
initialKeys: null,
|
||||
initialValue: null,
|
||||
initialKeysOnly: false
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
||||
/** @inheritdoc */
|
||||
_cleanType(value, options) {
|
||||
Object.entries(value).forEach(([k, v]) => value[k] = this.model.clean(v, options));
|
||||
return value;
|
||||
Object.entries(value).forEach(([k, v]) => (value[k] = this.model.clean(v, options)));
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
||||
/** @inheritdoc */
|
||||
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);
|
||||
return initial;
|
||||
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);
|
||||
return initial;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
||||
/**
|
||||
* Get the initial value for the provided key.
|
||||
* @param {string} key Key within the object being built.
|
||||
|
|
@ -52,21 +52,21 @@ export class MappingField extends foundry.data.fields.ObjectField {
|
|||
* @returns {*} Initial value based on provided field type.
|
||||
*/
|
||||
_getInitialValueForKey(key, object) {
|
||||
const initial = this.model.getInitialValue();
|
||||
return this.initialValue?.(key, initial, object) ?? initial;
|
||||
const initial = this.model.getInitialValue();
|
||||
return this.initialValue?.(key, initial, object) ?? initial;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
||||
/** @override */
|
||||
_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);
|
||||
_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);
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
||||
/**
|
||||
* Validate each value of the object.
|
||||
* @param {object} value The object to validate.
|
||||
|
|
@ -74,36 +74,36 @@ export class MappingField extends foundry.data.fields.ObjectField {
|
|||
* @returns {Object<Error>} An object of value-specific errors by key.
|
||||
*/
|
||||
_validateValues(value, options) {
|
||||
const errors = {};
|
||||
for ( const [k, v] of Object.entries(value) ) {
|
||||
const error = this.model.validate(v, options);
|
||||
if ( error ) errors[k] = error;
|
||||
}
|
||||
return errors;
|
||||
const errors = {};
|
||||
for (const [k, v] of Object.entries(value)) {
|
||||
const error = this.model.validate(v, options);
|
||||
if (error) errors[k] = error;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
||||
/** @override */
|
||||
initialize(value, model, options={}) {
|
||||
if ( !value ) return value;
|
||||
const obj = {};
|
||||
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 ) {
|
||||
const data = value[key] ?? this._getInitialValueForKey(key, value);
|
||||
obj[key] = this.model.initialize(data, model, options);
|
||||
}
|
||||
return obj;
|
||||
initialize(value, model, options = {}) {
|
||||
if (!value) return value;
|
||||
const obj = {};
|
||||
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) {
|
||||
const data = value[key] ?? this._getInitialValueForKey(key, value);
|
||||
obj[key] = this.model.initialize(data, model, options);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
||||
/** @inheritdoc */
|
||||
_getField(path) {
|
||||
if ( path.length === 0 ) return this;
|
||||
else if ( path.length === 1 ) return this.model;
|
||||
path.shift();
|
||||
return this.model._getField(path);
|
||||
if (path.length === 0) return this;
|
||||
else if (path.length === 1) return this.model;
|
||||
path.shift();
|
||||
return this.model._getField(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,75 +1,86 @@
|
|||
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({
|
||||
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({
|
||||
name: new fields.StringField({}),
|
||||
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 }),
|
||||
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.SchemaField({
|
||||
// damage: new fields.ArrayField(new fields.SchemaField({
|
||||
// type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.extendedDamageTypes), initial: SYSTEM.GENERAL.extendedDamageTypes.physical.id }),
|
||||
// value: new fields.StringField({}),
|
||||
// })),
|
||||
// uses: new fields.SchemaField({
|
||||
// nr: new fields.StringField({}),
|
||||
// refreshType: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.refreshTypes), initial: SYSTEM.GENERAL.refreshTypes.session.id }),
|
||||
// refreshed: new fields.BooleanField({ initial: true }),
|
||||
// }),
|
||||
// }),
|
||||
}
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
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({
|
||||
name: new fields.StringField({}),
|
||||
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
|
||||
}),
|
||||
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.SchemaField({
|
||||
// damage: new fields.ArrayField(new fields.SchemaField({
|
||||
// type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.extendedDamageTypes), initial: SYSTEM.GENERAL.extendedDamageTypes.physical.id }),
|
||||
// value: new fields.StringField({}),
|
||||
// })),
|
||||
// uses: new fields.SchemaField({
|
||||
// nr: new fields.StringField({}),
|
||||
// refreshType: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.refreshTypes), initial: SYSTEM.GENERAL.refreshTypes.session.id }),
|
||||
// refreshed: new fields.BooleanField({ initial: true }),
|
||||
// }),
|
||||
// }),
|
||||
};
|
||||
}
|
||||
|
||||
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){
|
||||
acc.push({ ...effect, valueData: this.#parseValues(effect.parseType, effect.valueData) });
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
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) {
|
||||
acc.push({ ...effect, valueData: this.#parseValues(effect.parseType, effect.valueData) });
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
return effectCategories;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return effectCategories;
|
||||
}
|
||||
|
||||
#parseValues(parseType, values){
|
||||
return Object.keys(values).reduce((acc, prop) => {
|
||||
acc[prop] = this.#parseValue(parseType, values[prop]);
|
||||
#parseValues(parseType, values) {
|
||||
return Object.keys(values).reduce((acc, prop) => {
|
||||
acc[prop] = this.#parseValue(parseType, values[prop]);
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
#parseValue(parseType, value) {
|
||||
switch(parseType){
|
||||
case SYSTEM.EFFECTS.parseTypes.number.id:
|
||||
return Number.parseInt(value);
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
switch (parseType) {
|
||||
case SYSTEM.EFFECTS.parseTypes.number.id:
|
||||
return Number.parseInt(value);
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
const fields = foundry.data.fields;
|
||||
|
||||
const featuresSchema = () => new fields.ArrayField(new fields.SchemaField({
|
||||
name: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
uuid: new fields.StringField({}),
|
||||
subclassLevel: new fields.StringField({}),
|
||||
}))
|
||||
const featuresSchema = () =>
|
||||
new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
name: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
uuid: new fields.StringField({}),
|
||||
subclassLevel: new fields.StringField({})
|
||||
})
|
||||
);
|
||||
|
||||
export default featuresSchema;
|
||||
export default featuresSchema;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
export default class DhpMiscellaneous extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
description: new fields.HTMLField({}),
|
||||
quantity: new fields.NumberField({ initial: 1, integer: true })
|
||||
}
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
description: new fields.HTMLField({}),
|
||||
quantity: new fields.NumberField({ initial: 1, integer: true })
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,39 @@
|
|||
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({
|
||||
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 }),
|
||||
}),
|
||||
levelMarks: new fields.ArrayField(new fields.NumberField({ nullable: true, initial: null, integer: true })),
|
||||
levelMark: new fields.NumberField({ nullable: true, initial: null, integer: true }),
|
||||
});
|
||||
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 })
|
||||
}),
|
||||
levelMarks: new fields.ArrayField(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()),
|
||||
hitPointSlots: new MappingField(new fields.BooleanField()),
|
||||
stressSlots: new MappingField(new fields.BooleanField()),
|
||||
experiences: new MappingField(new fields.ArrayField(new fields.StringField({}))),
|
||||
proficiency: new MappingField(new fields.BooleanField()),
|
||||
armorOrEvasionSlot: new MappingField(new fields.StringField({})),
|
||||
majorDamageThreshold2: new MappingField(new fields.BooleanField()),
|
||||
severeDamageThreshold2: new MappingField(new fields.BooleanField()),
|
||||
severeDamageThreshold3: new MappingField(new fields.BooleanField()),
|
||||
severeDamageThreshold4: new MappingField(new fields.BooleanField()),
|
||||
subclass: new MappingField(new fields.SchemaField({
|
||||
multiclass: new fields.BooleanField(),
|
||||
feature: new fields.StringField({}),
|
||||
})),
|
||||
multiclass: new MappingField(new fields.BooleanField()),
|
||||
attributes: new MappingField(new fields.BooleanField()),
|
||||
hitPointSlots: new MappingField(new fields.BooleanField()),
|
||||
stressSlots: new MappingField(new fields.BooleanField()),
|
||||
experiences: new MappingField(new fields.ArrayField(new fields.StringField({}))),
|
||||
proficiency: new MappingField(new fields.BooleanField()),
|
||||
armorOrEvasionSlot: new MappingField(new fields.StringField({})),
|
||||
majorDamageThreshold2: new MappingField(new fields.BooleanField()),
|
||||
severeDamageThreshold2: new MappingField(new fields.BooleanField()),
|
||||
severeDamageThreshold3: new MappingField(new fields.BooleanField()),
|
||||
severeDamageThreshold4: new MappingField(new fields.BooleanField()),
|
||||
subclass: new MappingField(
|
||||
new fields.SchemaField({
|
||||
multiclass: new fields.BooleanField(),
|
||||
feature: new fields.StringField({})
|
||||
})
|
||||
),
|
||||
multiclass: new MappingField(new fields.BooleanField())
|
||||
});
|
||||
|
||||
// const weapon = () => new fields.SchemaField({
|
||||
|
|
@ -48,450 +51,512 @@ const levelUpTier = () => ({
|
|||
|
||||
export default class DhpPC extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
return {
|
||||
resources: new fields.SchemaField({
|
||||
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 }),
|
||||
}),
|
||||
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 }),
|
||||
}),
|
||||
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 }),
|
||||
}),
|
||||
}),
|
||||
bonuses: 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({}),
|
||||
})),
|
||||
}),
|
||||
attributes: new fields.SchemaField({
|
||||
agility: attributeField(),
|
||||
strength: attributeField(),
|
||||
finesse: attributeField(),
|
||||
instinct: attributeField(),
|
||||
presence: 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}),
|
||||
}),
|
||||
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 }),
|
||||
}),
|
||||
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({
|
||||
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 }),
|
||||
}), {
|
||||
initial: [
|
||||
{ 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 }),
|
||||
}),
|
||||
pronouns: new fields.StringField({}),
|
||||
domainData: new fields.SchemaField({
|
||||
maxLoadout: 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({
|
||||
level: new fields.NumberField({ required: true, integer: true }),
|
||||
tier1: new fields.SchemaField({
|
||||
...levelUpTier()
|
||||
return {
|
||||
resources: new fields.SchemaField({
|
||||
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 })
|
||||
}),
|
||||
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 })
|
||||
}),
|
||||
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 })
|
||||
})
|
||||
}),
|
||||
tier2: new fields.SchemaField({
|
||||
...levelUpTier()
|
||||
}, { nullable: true, initial: null }),
|
||||
tier3: new fields.SchemaField({
|
||||
...levelUpTier()
|
||||
}, { 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({
|
||||
name: new fields.StringField({}),
|
||||
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 }),
|
||||
}),
|
||||
}
|
||||
bonuses: 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({})
|
||||
})
|
||||
)
|
||||
}),
|
||||
attributes: new fields.SchemaField({
|
||||
agility: attributeField(),
|
||||
strength: attributeField(),
|
||||
finesse: attributeField(),
|
||||
instinct: attributeField(),
|
||||
presence: 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 })
|
||||
}),
|
||||
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 })
|
||||
}),
|
||||
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({
|
||||
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 })
|
||||
}),
|
||||
{
|
||||
initial: [
|
||||
{ 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 })
|
||||
}),
|
||||
pronouns: new fields.StringField({}),
|
||||
domainData: new fields.SchemaField({
|
||||
maxLoadout: 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({
|
||||
level: new fields.NumberField({ required: true, integer: true }),
|
||||
tier1: new fields.SchemaField({
|
||||
...levelUpTier()
|
||||
}),
|
||||
tier2: new fields.SchemaField(
|
||||
{
|
||||
...levelUpTier()
|
||||
},
|
||||
{ nullable: true, initial: null }
|
||||
),
|
||||
tier3: new fields.SchemaField(
|
||||
{
|
||||
...levelUpTier()
|
||||
},
|
||||
{ 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({
|
||||
name: new fields.StringField({}),
|
||||
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 })
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
get canLevelUp(){
|
||||
// return Object.values(this.levels.data).some(x => !x.completed);
|
||||
return this.levelData.currentLevel !== this.levelData.changedLevel;
|
||||
get canLevelUp() {
|
||||
// return Object.values(this.levels.data).some(x => !x.completed);
|
||||
return this.levelData.currentLevel !== this.levelData.changedLevel;
|
||||
}
|
||||
|
||||
get tier(){
|
||||
return this.#getTier(this.levelData.currentLevel);
|
||||
get tier() {
|
||||
return this.#getTier(this.levelData.currentLevel);
|
||||
}
|
||||
|
||||
get ancestry(){
|
||||
return this.parent.items.find(x => x.type === 'ancestry') ?? null;
|
||||
get ancestry() {
|
||||
return this.parent.items.find(x => x.type === 'ancestry') ?? null;
|
||||
}
|
||||
|
||||
get class(){
|
||||
return this.parent.items.find(x => x.type === 'class' && !x.system.multiclass) ?? null;
|
||||
get class() {
|
||||
return this.parent.items.find(x => x.type === 'class' && !x.system.multiclass) ?? null;
|
||||
}
|
||||
|
||||
get multiclass(){
|
||||
return this.parent.items.find(x => x.type === 'class' && x.system.multiclass) ?? null;
|
||||
get multiclass() {
|
||||
return this.parent.items.find(x => x.type === 'class' && x.system.multiclass) ?? null;
|
||||
}
|
||||
|
||||
get multiclassSubclass(){
|
||||
return this.parent.items.find(x => x.type === 'subclass' && x.system.multiclass) ?? null;
|
||||
get multiclassSubclass() {
|
||||
return this.parent.items.find(x => x.type === 'subclass' && x.system.multiclass) ?? null;
|
||||
}
|
||||
|
||||
get subclass(){
|
||||
return this.parent.items.find(x => x.type === 'subclass' && !x.system.multiclass) ?? null;
|
||||
get subclass() {
|
||||
return this.parent.items.find(x => x.type === 'subclass' && !x.system.multiclass) ?? null;
|
||||
}
|
||||
|
||||
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)),
|
||||
},
|
||||
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 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)
|
||||
)
|
||||
},
|
||||
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(){
|
||||
return this.parent.items.find(x => x.type === 'community') ?? null;
|
||||
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(){
|
||||
const classDomains = this.class ? this.class.system.domains : [];
|
||||
const multiclassDomains = this.multiclass ? this.multiclass.system.domains : [];
|
||||
return [...classDomains, ...multiclassDomains]
|
||||
get domains() {
|
||||
const classDomains = this.class ? this.class.system.domains : [];
|
||||
const multiclassDomains = this.multiclass ? this.multiclass.system.domains : [];
|
||||
return [...classDomains, ...multiclassDomains];
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
return {
|
||||
loadout: loadout,
|
||||
vault: vault,
|
||||
total: [...loadout, ...vault]
|
||||
};
|
||||
return {
|
||||
loadout: loadout,
|
||||
vault: vault,
|
||||
total: [...loadout, ...vault]
|
||||
};
|
||||
}
|
||||
|
||||
get armor(){
|
||||
return this.parent.items.find(x => x.type === '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);
|
||||
return {
|
||||
primary: this.#weaponData(primaryWeapon),
|
||||
secondary: this.#weaponData(secondaryWeapon),
|
||||
burden: this.getBurden(primaryWeapon, secondaryWeapon)
|
||||
};
|
||||
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),
|
||||
burden: this.getBurden(primaryWeapon, secondaryWeapon)
|
||||
};
|
||||
}
|
||||
|
||||
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);
|
||||
return {
|
||||
first: this.#weaponData(inventoryWeaponFirst),
|
||||
second: this.#weaponData(inventoryWeaponSecond),
|
||||
};
|
||||
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
|
||||
);
|
||||
return {
|
||||
first: this.#weaponData(inventoryWeaponFirst),
|
||||
second: this.#weaponData(inventoryWeaponSecond)
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
return nr;
|
||||
}, 0);
|
||||
return nr;
|
||||
}, 0);
|
||||
|
||||
nr.push(...Array(nrAttributeMarks).fill(Number.parseInt(level)));
|
||||
nr.push(...Array(nrAttributeMarks).fill(Number.parseInt(level)));
|
||||
|
||||
return nr;
|
||||
}, []);
|
||||
return nr;
|
||||
}, []);
|
||||
}
|
||||
|
||||
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)){
|
||||
acc.push(attribute);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
get effects(){
|
||||
return this.parent.items.reduce((acc, item) => {
|
||||
const effects = item.system.effectData;
|
||||
if(effects && !item.system.disabled){
|
||||
for(var key in effects){
|
||||
const effect = effects[key];
|
||||
for(var effectEntry of effect){
|
||||
if(!acc[key]) acc[key] = [];
|
||||
acc[key].push({ name: item.name, value: effectEntry });
|
||||
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)) {
|
||||
acc.push(attribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
get refreshableFeatures(){
|
||||
return this.parent.items.reduce((acc, x) => {
|
||||
if(x.type === 'feature' && x.system.refreshData.type){
|
||||
acc[x.system.refreshData.type].push(x);
|
||||
}
|
||||
get effects() {
|
||||
return this.parent.items.reduce((acc, item) => {
|
||||
const effects = item.system.effectData;
|
||||
if (effects && !item.system.disabled) {
|
||||
for (var key in effects) {
|
||||
const effect = effects[key];
|
||||
for (var effectEntry of effect) {
|
||||
if (!acc[key]) acc[key] = [];
|
||||
acc[key].push({ name: item.name, value: effectEntry });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, { shortRest: [], longRest: [] });
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
#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],
|
||||
},
|
||||
feature: CONFIG.daggerheart.ITEM.weaponFeatures[weapon.system.feature],
|
||||
img: weapon.img,
|
||||
uuid: weapon.uuid
|
||||
} : null
|
||||
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: [] }
|
||||
);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
this.evasion = this.class?.system?.evasion ?? 0;
|
||||
// this.armor.value = this.activeArmor?.baseScore ?? 0;
|
||||
this.damageThresholds = this.class?.system?.damageThresholds ?? { minor: 0, major: 0, severe: 0 };
|
||||
|
||||
this.applyLevels();
|
||||
this.applyEffects();
|
||||
}
|
||||
|
||||
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){
|
||||
var levelData = this.levelData.levelups[level];
|
||||
for(var tier in levelData){
|
||||
var tierData = levelData[tier];
|
||||
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;
|
||||
|
||||
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;
|
||||
#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]
|
||||
},
|
||||
feature: CONFIG.daggerheart.ITEM.weaponFeatures[weapon.system.feature],
|
||||
img: weapon.img,
|
||||
uuid: weapon.uuid
|
||||
}
|
||||
: null;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
this.evasion = this.class?.system?.evasion ?? 0;
|
||||
// this.armor.value = this.activeArmor?.baseScore ?? 0;
|
||||
this.damageThresholds = this.class?.system?.damageThresholds ?? { minor: 0, major: 0, severe: 0 };
|
||||
|
||||
this.applyLevels();
|
||||
this.applyEffects();
|
||||
}
|
||||
|
||||
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) {
|
||||
var levelData = this.levelData.levelups[level];
|
||||
for (var tier in levelData) {
|
||||
var tierData = levelData[tier];
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
severeThresholdBonus += Object.keys(tierData.severeDamageThreshold3).length * 3;
|
||||
severeThresholdBonus += Object.keys(tierData.severeDamageThreshold4).length * 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.resources.health.max += healthBonus;
|
||||
this.resources.stress.max += stressBonus;
|
||||
this.proficiency.value += proficiencyBonus;
|
||||
this.evasion += evasionBonus;
|
||||
this.armorMarks = {
|
||||
max: this.armor ? this.armor.system.marks.max + armorBonus : 0,
|
||||
value: this.armor ? this.armor.system.marks.value : 0
|
||||
};
|
||||
this.damageThresholds.minor += minorThresholdBonus;
|
||||
this.damageThresholds.major += majorThresholdBonus;
|
||||
this.damageThresholds.severe += severeThresholdBonus;
|
||||
|
||||
this.experiences = this.experiences.map(x => ({ ...x, value: x.value + (experienceBonuses[x.id] ?? 0) }));
|
||||
|
||||
const subclassFeatures = this.subclassFeatures;
|
||||
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));
|
||||
} 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));
|
||||
}
|
||||
}
|
||||
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)
|
||||
);
|
||||
} 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));
|
||||
}
|
||||
}
|
||||
|
||||
//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);
|
||||
this.domainData.maxCards += 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;
|
||||
|
||||
majorThresholdBonus += Object.keys(tierData.majorDamageThreshold2).length * 2;
|
||||
severeThresholdBonus += Object.keys(tierData.severeDamageThreshold2).length * 2;
|
||||
severeThresholdBonus += Object.keys(tierData.severeDamageThreshold3).length * 3;
|
||||
severeThresholdBonus += Object.keys(tierData.severeDamageThreshold4).length * 4;
|
||||
}
|
||||
switch (tier) {
|
||||
case 'tier1':
|
||||
this.damageThresholds.severe += 2;
|
||||
break;
|
||||
case 'tier2':
|
||||
this.damageThresholds.major += 1;
|
||||
this.damageThresholds.severe += 3;
|
||||
break;
|
||||
case 'tier3':
|
||||
this.damageThresholds.major += 2;
|
||||
this.damageThresholds.severe += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.resources.health.max += healthBonus;
|
||||
this.resources.stress.max += stressBonus;
|
||||
this.proficiency.value += proficiencyBonus;
|
||||
this.evasion += evasionBonus;
|
||||
this.armorMarks = {
|
||||
max: this.armor ? this.armor.system.marks.max + armorBonus : 0,
|
||||
value: this.armor ? this.armor.system.marks.value : 0,
|
||||
};
|
||||
this.damageThresholds.minor += minorThresholdBonus;
|
||||
this.damageThresholds.major += majorThresholdBonus;
|
||||
this.damageThresholds.severe += severeThresholdBonus;
|
||||
|
||||
this.experiences = this.experiences.map(x => ({ ...x, value: x.value + (experienceBonuses[x.id] ?? 0) }));
|
||||
|
||||
const subclassFeatures = this.subclassFeatures;
|
||||
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);
|
||||
} 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);
|
||||
applyEffects() {
|
||||
const effects = this.effects;
|
||||
for (var key in effects) {
|
||||
const effectType = effects[key];
|
||||
for (var effect of effectType) {
|
||||
switch (key) {
|
||||
case SYSTEM.EFFECTS.effectTypes.health.id:
|
||||
this.resources.health.max += effect.value.valueData.value;
|
||||
break;
|
||||
case SYSTEM.EFFECTS.effectTypes.stress.id:
|
||||
this.resources.stress.max += effect.value.valueData.value;
|
||||
break;
|
||||
case SYSTEM.EFFECTS.effectTypes.damage.id:
|
||||
this.bonuses.damage.push({
|
||||
value: getPathValue(effect.value.valueData.value, this),
|
||||
type: 'physical',
|
||||
description: effect.name,
|
||||
hopeIncrease: effect.value.valueData.hopeIncrease,
|
||||
initiallySelected: effect.value.initiallySelected,
|
||||
appliesOn: effect.value.appliesOn
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//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);
|
||||
this.domainData.maxCards += 1;
|
||||
}
|
||||
|
||||
switch(tier){
|
||||
case 'tier1':
|
||||
this.damageThresholds.severe += 2;
|
||||
break;
|
||||
case 'tier2':
|
||||
this.damageThresholds.major += 1;
|
||||
this.damageThresholds.severe += 3;
|
||||
break;
|
||||
case 'tier3':
|
||||
this.damageThresholds.major += 2;
|
||||
this.damageThresholds.severe += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
applyEffects(){
|
||||
const effects = this.effects;
|
||||
for(var key in effects){
|
||||
const effectType = effects[key];
|
||||
for(var effect of effectType) {
|
||||
switch(key) {
|
||||
case SYSTEM.EFFECTS.effectTypes.health.id:
|
||||
this.resources.health.max += effect.value.valueData.value;
|
||||
break;
|
||||
case SYSTEM.EFFECTS.effectTypes.stress.id:
|
||||
this.resources.stress.max += effect.value.valueData.value;
|
||||
break;
|
||||
case SYSTEM.EFFECTS.effectTypes.damage.id:
|
||||
this.bonuses.damage.push({
|
||||
value: getPathValue(effect.value.valueData.value, this),
|
||||
type: 'physical',
|
||||
description: effect.name,
|
||||
hopeIncrease: effect.value.valueData.hopeIncrease,
|
||||
initiallySelected: effect.value.initiallySelected,
|
||||
appliesOn: effect.value.appliesOn,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
getBurden(primary, secondary) {
|
||||
const twoHanded =
|
||||
primary?.system?.burden === 'twoHanded' ||
|
||||
secondary?.system?.burden === 'twoHanded' ||
|
||||
(primary?.system?.burden === 'oneHanded' && secondary?.system?.burden === 'oneHanded');
|
||||
const oneHanded =
|
||||
!twoHanded && (primary?.system?.burden === 'oneHanded' || secondary?.system?.burden === 'oneHanded');
|
||||
|
||||
return twoHanded ? 'twoHanded' : oneHanded ? 'oneHanded' : null;
|
||||
}
|
||||
|
||||
getBurden(primary, secondary){
|
||||
const twoHanded =
|
||||
primary?.system?.burden === 'twoHanded' ||
|
||||
secondary?.system?.burden === 'twoHanded' ||
|
||||
(
|
||||
primary?.system?.burden === 'oneHanded' &&
|
||||
secondary?.system?.burden === 'oneHanded'
|
||||
);
|
||||
const oneHanded =
|
||||
!twoHanded &&
|
||||
(
|
||||
primary?.system?.burden === 'oneHanded' ||
|
||||
secondary?.system?.burden === 'oneHanded'
|
||||
);
|
||||
|
||||
return twoHanded ? 'twoHanded' : oneHanded ? 'oneHanded' : null;
|
||||
isSameTier(level) {
|
||||
return this.#getTier(this.levelData.currentLevel) === this.#getTier(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;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
#getTier(level){
|
||||
if(level >= 8) return 3;
|
||||
else if(level >= 5) return 2;
|
||||
else if(level >= 2) return 1;
|
||||
else return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +1,39 @@
|
|||
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 {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
description: new fields.HTMLField({}),
|
||||
spellcastingTrait: new fields.StringField({ choices: SYSTEM.ACTOR.abilities, integer: false, nullable: true, initial: null }),
|
||||
foundationFeature: new fields.SchemaField({
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
description: new fields.HTMLField({}),
|
||||
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)),
|
||||
}),
|
||||
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)),
|
||||
}),
|
||||
multiclass: new fields.NumberField({ initial: null, nullable: true, integer: true }),
|
||||
}
|
||||
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))
|
||||
}),
|
||||
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))
|
||||
}),
|
||||
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))
|
||||
}),
|
||||
multiclass: new fields.NumberField({ initial: null, nullable: true, integer: true })
|
||||
};
|
||||
}
|
||||
|
||||
get multiclassTier(){
|
||||
get multiclassTier() {
|
||||
return getTier(this.multiclass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,50 @@
|
|||
export default class DhpWeapon extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
active: new fields.BooleanField({ initial: false }),
|
||||
inventoryWeapon: new fields.NumberField({ initial: null, nullable: true, integer: true }),
|
||||
secondary: new fields.BooleanField({ initial: false }),
|
||||
trait: new fields.StringField({ choices: SYSTEM.ACTOR.abilities, integer: false }),
|
||||
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 }),
|
||||
}),
|
||||
burden: new fields.StringField({ choices: SYSTEM.GENERAL.burden, integer: false }),
|
||||
feature: new fields.StringField({ choices: SYSTEM.ITEM.weaponFeatures, integer: false, blank:true }),
|
||||
quantity: new fields.NumberField({ initial: 1, integer: true }),
|
||||
description: new fields.HTMLField({}),
|
||||
}
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
active: new fields.BooleanField({ initial: false }),
|
||||
inventoryWeapon: new fields.NumberField({ initial: null, nullable: true, integer: true }),
|
||||
secondary: new fields.BooleanField({ initial: false }),
|
||||
trait: new fields.StringField({ choices: SYSTEM.ACTOR.abilities, integer: false }),
|
||||
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 })
|
||||
}),
|
||||
burden: new fields.StringField({ choices: SYSTEM.GENERAL.burden, integer: false }),
|
||||
feature: new fields.StringField({ choices: SYSTEM.ITEM.weaponFeatures, integer: false, blank: true }),
|
||||
quantity: new fields.NumberField({ initial: 1, integer: true }),
|
||||
description: new fields.HTMLField({})
|
||||
};
|
||||
}
|
||||
|
||||
prepareDerivedData(){
|
||||
if(this.parent.parent){
|
||||
this.applyEffects();
|
||||
}
|
||||
}
|
||||
|
||||
applyEffects(){
|
||||
const effects = this.parent.parent.system.effects;
|
||||
for(var key in effects){
|
||||
const effectType = effects[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){
|
||||
this.range = effect.valueData.value;
|
||||
}
|
||||
|
||||
break;
|
||||
// case SYSTEM.EFFECTS.effectTypes.damage.id:
|
||||
|
||||
// if(this.damage.type === 'physical') this.damage.value = (`${this.damage.value} + ${this.parent.parent.system.levelData.currentLevel}`);
|
||||
// break;
|
||||
}
|
||||
prepareDerivedData() {
|
||||
if (this.parent.parent) {
|
||||
this.applyEffects();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
applyEffects() {
|
||||
const effects = this.parent.parent.system.effects;
|
||||
for (var key in effects) {
|
||||
const effectType = effects[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
|
||||
) {
|
||||
this.range = effect.valueData.value;
|
||||
}
|
||||
|
||||
break;
|
||||
// case SYSTEM.EFFECTS.effectTypes.damage.id:
|
||||
|
||||
// if(this.damage.type === 'physical') this.damage.value = (`${this.damage.value} + ${this.parent.parent.system.levelData.currentLevel}`);
|
||||
// break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,41 +5,41 @@ 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;
|
||||
return obj;
|
||||
let b = this.data.buttons[key];
|
||||
b.cssClass = (this.data.default === key ? [key, 'default', 'bright'] : [key]).join(' ');
|
||||
if (b.condition !== false) obj[key] = b;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
const content = await this.data.content;
|
||||
const content = await this.data.content;
|
||||
|
||||
return {
|
||||
content: content,
|
||||
buttons: buttons
|
||||
content: content,
|
||||
buttons: buttons
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
$(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,47 +48,47 @@ 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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param {*} data
|
||||
* choices, actor, title, cancelMessage, nrChoices, validate
|
||||
* @returns
|
||||
* choices, actor, title, cancelMessage, nrChoices, validate
|
||||
* @returns
|
||||
*/
|
||||
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,
|
||||
actor: data.actor,
|
||||
nrChoices: data.nrChoices ?? 1,
|
||||
validate: data.validate
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
export { default as DhpActor } from './actor.mjs';
|
||||
export { default as DhpItem } from './item.mjs';
|
||||
export { default as DhpCombat } from './combat.mjs';
|
||||
export { default as DhpCombat } from './combat.mjs';
|
||||
|
|
|
|||
|
|
@ -1,350 +1,416 @@
|
|||
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'){
|
||||
data.prototypeToken = { actorLink: true, disposition: 1, sight: { enabled: true } };
|
||||
}
|
||||
|
||||
super._preCreate(data, changes, user);
|
||||
}
|
||||
|
||||
prepareData(){
|
||||
super.prepareData();
|
||||
}
|
||||
|
||||
async _preUpdate(changed, options, user) {
|
||||
//Level Down
|
||||
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){
|
||||
acc[`-=${x}`] = null;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
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) };
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
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){
|
||||
const multiclassFeatures = this.items.filter(x => x.system.multiclass);
|
||||
for(var feature of multiclassFeatures){
|
||||
await feature.delete();
|
||||
}
|
||||
_preCreate(data, changes, user) {
|
||||
if (data.type === 'pc') {
|
||||
data.prototypeToken = { actorLink: true, disposition: 1, sight: { enabled: true } };
|
||||
}
|
||||
}
|
||||
|
||||
super._preUpdate(changed, options, user);
|
||||
super._preCreate(data, changes, user);
|
||||
}
|
||||
|
||||
prepareData() {
|
||||
super.prepareData();
|
||||
}
|
||||
|
||||
async _preUpdate(changed, options, user) {
|
||||
//Level Down
|
||||
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) {
|
||||
acc[`-=${x}`] = null;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
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
|
||||
)
|
||||
};
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
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
|
||||
) {
|
||||
const multiclassFeatures = this.items.filter(x => x.system.multiclass);
|
||||
for (var feature of multiclassFeatures) {
|
||||
await feature.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super._preUpdate(changed, options, user);
|
||||
}
|
||||
|
||||
async diceRoll(modifier, shiftKey) {
|
||||
if(this.type === 'pc'){
|
||||
return await this.dualityRoll(modifier, shiftKey);
|
||||
}
|
||||
else {
|
||||
return await this.npcRoll(modifier, shiftKey);
|
||||
}
|
||||
if (this.type === 'pc') {
|
||||
return await this.dualityRoll(modifier, shiftKey);
|
||||
} else {
|
||||
return await this.npcRoll(modifier, shiftKey);
|
||||
}
|
||||
}
|
||||
|
||||
async npcRoll(modifier, shiftKey) {
|
||||
let nrDice = 1;
|
||||
let advantage = null;
|
||||
let nrDice = 1;
|
||||
let advantage = null;
|
||||
|
||||
const modifiers = [
|
||||
{
|
||||
value: Number.parseInt(modifier.value),
|
||||
label: modifier.value >= 0 ? `+${modifier.value}` : `-${modifier.value}`,
|
||||
title: modifier.title,
|
||||
const modifiers = [
|
||||
{
|
||||
value: Number.parseInt(modifier.value),
|
||||
label: modifier.value >= 0 ? `+${modifier.value}` : `-${modifier.value}`,
|
||||
title: modifier.title
|
||||
}
|
||||
];
|
||||
if (!shiftKey) {
|
||||
const dialogClosed = new Promise((resolve, _) => {
|
||||
new NpcRollSelectionDialog(this.system.experiences, resolve).render(true);
|
||||
});
|
||||
const result = await dialogClosed;
|
||||
|
||||
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
|
||||
})
|
||||
);
|
||||
}
|
||||
];
|
||||
if(!shiftKey) {
|
||||
const dialogClosed = new Promise((resolve, _) => {
|
||||
new NpcRollSelectionDialog(this.system.experiences, resolve).render(true);
|
||||
});
|
||||
const result = await dialogClosed;
|
||||
|
||||
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 }))
|
||||
}
|
||||
|
||||
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 })));
|
||||
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 };
|
||||
return { roll, diceResults: diceResults, modifiers: modifiers };
|
||||
}
|
||||
|
||||
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,
|
||||
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
|
||||
}
|
||||
];
|
||||
if (!shiftKey) {
|
||||
const dialogClosed = new Promise((resolve, _) => {
|
||||
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
|
||||
})
|
||||
);
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
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'
|
||||
};
|
||||
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'
|
||||
};
|
||||
rollResult.dice[2].options.appearance = {
|
||||
colorset: 'bloodmoon',
|
||||
foreground: '#000000',
|
||||
background: '#430070',
|
||||
outline: '#b30000',
|
||||
edge: '#000000',
|
||||
texture: 'bloodmoon',
|
||||
material: 'metal',
|
||||
font: 'Arial Black',
|
||||
system: 'standard'
|
||||
};
|
||||
} 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'
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (disadvantage) {
|
||||
rollResult = { ...rollResult, total: rollResult.total - Math.max(hope, disadvantage) };
|
||||
}
|
||||
if (advantage) {
|
||||
rollResult = { ...rollResult, total: 'Select Hope Die' };
|
||||
}
|
||||
];
|
||||
if(!shiftKey) {
|
||||
const dialogClosed = new Promise((resolve, _) => {
|
||||
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 }))
|
||||
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 && hope > fear) {
|
||||
await this.update({
|
||||
'system.resources.hope.value': Math.min(
|
||||
this.system.resources.hope.value + 1,
|
||||
this.system.resources.hope.max
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
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"
|
||||
};
|
||||
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"
|
||||
};
|
||||
rollResult.dice[2].options.appearance = {
|
||||
colorset:"bloodmoon",
|
||||
foreground: "#000000",
|
||||
background: "#430070",
|
||||
outline: "#b30000",
|
||||
edge: "#000000",
|
||||
texture: "bloodmoon",
|
||||
material: "metal",
|
||||
font: "Arial Black",
|
||||
system: "standard"
|
||||
};
|
||||
}
|
||||
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"
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if(disadvantage){
|
||||
rollResult = {...rollResult, total: rollResult.total - Math.max(hope, disadvantage) };
|
||||
}
|
||||
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),
|
||||
'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){
|
||||
let rollString = damage.value;
|
||||
let bonusDamage = damage.bonusDamage?.filter(x => x.initiallySelected) ?? [];
|
||||
if(!shiftKey) {
|
||||
const dialogClosed = new Promise((resolve, _) => {
|
||||
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 });
|
||||
async damageRoll(damage, shiftKey) {
|
||||
let rollString = damage.value;
|
||||
let bonusDamage = damage.bonusDamage?.filter(x => x.initiallySelected) ?? [];
|
||||
if (!shiftKey) {
|
||||
const dialogClosed = new Promise((resolve, _) => {
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const roll = new Roll(rollString);
|
||||
let rollResult = await roll.evaluate();
|
||||
const roll = new Roll(rollString);
|
||||
let rollResult = await roll.evaluate();
|
||||
|
||||
const dice = [];
|
||||
const modifiers = [];
|
||||
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){
|
||||
const dice = [];
|
||||
const modifiers = [];
|
||||
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;
|
||||
modifiers.push(`${operator}${term.number}`);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if(term.number){
|
||||
const operator = i === 0 ? '' : rollResult.terms[i-1].operator;
|
||||
modifiers.push(`${operator}${term.number}`);
|
||||
}
|
||||
}
|
||||
const cls = getDocumentClass('ChatMessage');
|
||||
const msg = new cls({
|
||||
user: game.user.id,
|
||||
content: await renderTemplate('systems/daggerheart/templates/chat/damage-roll.hbs', {
|
||||
roll: rollString,
|
||||
total: rollResult.total,
|
||||
dice: dice,
|
||||
modifiers: modifiers
|
||||
}),
|
||||
rolls: [roll]
|
||||
});
|
||||
|
||||
const cls = getDocumentClass("ChatMessage");
|
||||
const msg = new cls({
|
||||
user: game.user.id,
|
||||
content: await renderTemplate("systems/daggerheart/templates/chat/damage-roll.hbs", {
|
||||
roll: rollString,
|
||||
total: rollResult.total,
|
||||
dice: dice,
|
||||
modifiers: modifiers
|
||||
}),
|
||||
rolls: [roll]
|
||||
});
|
||||
|
||||
cls.create(msg.toObject());
|
||||
cls.create(msg.toObject());
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
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){
|
||||
await this.update(update);
|
||||
} else {
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.GMUpdate,
|
||||
data: {
|
||||
action: GMUpdateEvent.UpdateDocument,
|
||||
uuid: this.uuid,
|
||||
update: update,
|
||||
}
|
||||
});
|
||||
}
|
||||
if (game.user.isGM) {
|
||||
await this.update(update);
|
||||
} else {
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.GMUpdate,
|
||||
data: {
|
||||
action: GMUpdateEvent.UpdateDocument,
|
||||
uuid: this.uuid,
|
||||
update: update
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async takeHealing(healing, 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) };
|
||||
break;
|
||||
case SYSTEM.GENERAL.healingTypes.stress.id:
|
||||
update = { "system.resources.stress.value": Math.max(this.system.resources.stress.value - healing, 0) };
|
||||
break;
|
||||
}
|
||||
let update = {};
|
||||
switch (type) {
|
||||
case SYSTEM.GENERAL.healingTypes.health.id:
|
||||
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) };
|
||||
break;
|
||||
}
|
||||
|
||||
if(game.user.isGM){
|
||||
await this.update(update);
|
||||
} else {
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.GMUpdate,
|
||||
data: {
|
||||
action: GMUpdateEvent.UpdateDocument,
|
||||
uuid: this.uuid,
|
||||
update: update,
|
||||
}
|
||||
});
|
||||
}
|
||||
if (game.user.isGM) {
|
||||
await this.update(update);
|
||||
} else {
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.GMUpdate,
|
||||
data: {
|
||||
action: GMUpdateEvent.UpdateDocument,
|
||||
uuid: this.uuid,
|
||||
update: update
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async emulateItemDrop(data) {
|
||||
const event = new DragEvent("drop", { altKey: game.keyboard.isModifierActive("Alt") });
|
||||
return this.sheet._onDropItem(event, { data: data });
|
||||
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"));
|
||||
return;
|
||||
}
|
||||
|
||||
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){
|
||||
let roll = { formula: action.damage.value, result: action.damage.value };
|
||||
if(Number.isNaN(Number.parseInt(action.damage.value))){
|
||||
roll = await new Roll(`1${action.damage.value}`).evaluate();
|
||||
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'));
|
||||
return;
|
||||
}
|
||||
|
||||
const cls = getDocumentClass("ChatMessage");
|
||||
const msg = new cls({
|
||||
user: game.user.id,
|
||||
content: await renderTemplate("systems/daggerheart/templates/chat/damage-roll.hbs", {
|
||||
roll: roll.formula,
|
||||
total: roll.result,
|
||||
type: action.damage.type,
|
||||
}),
|
||||
});
|
||||
|
||||
cls.create(msg.toObject());
|
||||
}
|
||||
|
||||
if(action.healing.type){
|
||||
let roll = { formula: action.healing.value, result: action.healing.value };
|
||||
if(Number.isNaN(Number.parseInt(action.healing.value))){
|
||||
roll = await new Roll(`1${action.healing.value}`).evaluate();
|
||||
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 cls = getDocumentClass("ChatMessage");
|
||||
const msg = new cls({
|
||||
user: game.user.id,
|
||||
content: await renderTemplate("systems/daggerheart/templates/chat/healing-roll.hbs", {
|
||||
roll: roll.formula,
|
||||
total: roll.result,
|
||||
type: action.healing.type,
|
||||
}),
|
||||
});
|
||||
|
||||
cls.create(msg.toObject());
|
||||
}
|
||||
// const targets = otherTarget ? userTargets : [game.user.character];
|
||||
if (action.damage.type) {
|
||||
let roll = { formula: action.damage.value, result: 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 msg = new cls({
|
||||
user: game.user.id,
|
||||
content: await renderTemplate('systems/daggerheart/templates/chat/damage-roll.hbs', {
|
||||
roll: roll.formula,
|
||||
total: roll.result,
|
||||
type: action.damage.type
|
||||
})
|
||||
});
|
||||
|
||||
cls.create(msg.toObject());
|
||||
}
|
||||
|
||||
if (action.healing.type) {
|
||||
let roll = { formula: action.healing.value, result: 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 msg = new cls({
|
||||
user: game.user.id,
|
||||
content: await renderTemplate('systems/daggerheart/templates/chat/healing-roll.hbs', {
|
||||
roll: roll.formula,
|
||||
total: roll.result,
|
||||
type: action.healing.type
|
||||
})
|
||||
});
|
||||
|
||||
cls.create(msg.toObject());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
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;
|
||||
|
||||
|
||||
return aVal - bVal;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
|
||||
const update = automateActionPoints ?
|
||||
{ "system.activeCombatant": combatantId, "system.actions": Math.max(this.system.actions-1, 0) } :
|
||||
{ "system.activeCombatant": combatantId };
|
||||
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 };
|
||||
|
||||
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,
|
||||
|
|
@ -38,4 +41,4 @@ export default class DhpCombat extends Combat {
|
|||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,72 +1,79 @@
|
|||
export default class DhpItem extends Item {
|
||||
_preCreate(data, changes, user){
|
||||
super._preCreate(data, changes, user);
|
||||
_preCreate(data, changes, user) {
|
||||
super._preCreate(data, changes, user);
|
||||
}
|
||||
|
||||
prepareData(){
|
||||
prepareData() {
|
||||
super.prepareData();
|
||||
|
||||
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())];
|
||||
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(){
|
||||
return ['weapon', 'armor', 'miscellaneous', 'consumable'].includes(this.type);
|
||||
isInventoryItem() {
|
||||
return ['weapon', 'armor', 'miscellaneous', 'consumable'].includes(this.type);
|
||||
}
|
||||
|
||||
_onUpdate(data, options, userId) {
|
||||
super._onUpdate(data, options, userId);
|
||||
super._onUpdate(data, options, userId);
|
||||
}
|
||||
|
||||
static async createDialog(data = {}, { parent = null, pack = null, ...options } = {}) {
|
||||
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);
|
||||
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 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 };
|
||||
return obj;
|
||||
}, {});
|
||||
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);
|
||||
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 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 };
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
// Render the document creation form
|
||||
const html = await renderTemplate("systems/daggerheart/templates/sidebar/documentCreate.hbs", {
|
||||
folders,
|
||||
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],
|
||||
},
|
||||
hasTypes: types.length > 1
|
||||
});
|
||||
// Render the document creation form
|
||||
const html = await renderTemplate('systems/daggerheart/templates/sidebar/documentCreate.hbs', {
|
||||
folders,
|
||||
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
|
||||
]
|
||||
},
|
||||
hasTypes: types.length > 1
|
||||
});
|
||||
|
||||
// Render the confirmation dialog window
|
||||
return Dialog.prompt({
|
||||
title: title,
|
||||
content: html,
|
||||
label: title,
|
||||
callback: html => {
|
||||
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});
|
||||
},
|
||||
rejectClose: false,
|
||||
options
|
||||
});
|
||||
// Render the confirmation dialog window
|
||||
return Dialog.prompt({
|
||||
title: title,
|
||||
content: html,
|
||||
label: title,
|
||||
callback: html => {
|
||||
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 });
|
||||
},
|
||||
rejectClose: false,
|
||||
options
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(' ');
|
||||
return acc;
|
||||
}, [])
|
||||
.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);
|
||||
}
|
||||
|
||||
|
|
@ -102,4 +110,4 @@ export default class RegisterHandlebarsHelpers {
|
|||
console.log(JSON.stringify(a));
|
||||
return a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -8,13 +8,13 @@ export function handleSocketEvent({action=null, data={}}={}) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const socketEvent = {
|
||||
GMUpdate: "DhpGMUpdate",
|
||||
DhpFearUpdate: "DhpFearUpdate",
|
||||
GMUpdate: 'DhpGMUpdate',
|
||||
DhpFearUpdate: 'DhpFearUpdate'
|
||||
};
|
||||
|
||||
export const GMUpdateEvent = {
|
||||
UpdateDocument: "DhpGMUpdateDocument",
|
||||
UpdateFear: "DhpUpdateFear"
|
||||
};
|
||||
UpdateDocument: 'DhpGMUpdateDocument',
|
||||
UpdateFear: 'DhpUpdateFear'
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,24 +34,23 @@ 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)){
|
||||
case 1:
|
||||
switch (Math.floor((level + 1) / 3)) {
|
||||
case 1:
|
||||
return asNr ? 1 : 'tier1';
|
||||
case 2:
|
||||
return asNr ? 2 : 'tier2';
|
||||
|
|
@ -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});
|
||||
return i ? p.titleCase() : p;
|
||||
}).join("");
|
||||
return Number.isNumeric(length) ? id.slice(0, length).padEnd(length, "0") : id;
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
}
|
||||
|
||||
setupHooks(){
|
||||
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() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,200 +1,199 @@
|
|||
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) {
|
||||
super(data, context);
|
||||
super(data, context);
|
||||
|
||||
Hooks.on(socketEvent.DhpFearUpdate, this.onFearUpdate);
|
||||
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 currentFear = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear);
|
||||
const value = currentFear + 1;
|
||||
|
||||
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 },
|
||||
});
|
||||
await game.combat.update({ "system.actions": game.combat.system.actions-2 });
|
||||
}
|
||||
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 }
|
||||
});
|
||||
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);
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.GMUpdate,
|
||||
data: { action: GMUpdateEvent.UpdateFear, update: value },
|
||||
});
|
||||
await game.combat.update({ "system.actions": game.combat.system.actions+2 });
|
||||
}
|
||||
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);
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.GMUpdate,
|
||||
data: { action: GMUpdateEvent.UpdateFear, update: value }
|
||||
});
|
||||
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);
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.GMUpdate,
|
||||
data: { action: GMUpdateEvent.UpdateFear, update: value },
|
||||
});
|
||||
}
|
||||
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);
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.GMUpdate,
|
||||
data: { action: GMUpdateEvent.UpdateFear, update: value }
|
||||
});
|
||||
}
|
||||
|
||||
this.render();
|
||||
this.render();
|
||||
}
|
||||
|
||||
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);
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.GMUpdate,
|
||||
data: { action: GMUpdateEvent.UpdateFear, update: value },
|
||||
});
|
||||
}
|
||||
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);
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.GMUpdate,
|
||||
data: { action: GMUpdateEvent.UpdateFear, update: value }
|
||||
});
|
||||
}
|
||||
|
||||
this.render();
|
||||
this.render();
|
||||
}
|
||||
|
||||
async getData(options={}) {
|
||||
async getData(options = {}) {
|
||||
let context = await super.getData(options);
|
||||
|
||||
|
||||
// Get the combat encounters possible for the viewed Scene
|
||||
const combat = this.viewed;
|
||||
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, {
|
||||
combats: combats,
|
||||
currentIndex: currentIdx + 1,
|
||||
combatCount: combats.length,
|
||||
hasCombat: hasCombat,
|
||||
combat,
|
||||
turns: [],
|
||||
previousId,
|
||||
nextId,
|
||||
started: this.started,
|
||||
control: false,
|
||||
settings,
|
||||
linked: combat?.scene !== null,
|
||||
labels: {}
|
||||
combats: combats,
|
||||
currentIndex: currentIdx + 1,
|
||||
combatCount: combats.length,
|
||||
hasCombat: hasCombat,
|
||||
combat,
|
||||
turns: [],
|
||||
previousId,
|
||||
nextId,
|
||||
started: this.started,
|
||||
control: false,
|
||||
settings,
|
||||
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;
|
||||
|
||||
// Prepare turn data
|
||||
const resource = combatant.permission >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER ? combatant.resource : null;
|
||||
const turn = {
|
||||
id: combatant.id,
|
||||
name: combatant.name,
|
||||
img: await this._getCombatantThumbnail(combatant),
|
||||
active: combatant.id === combat.system.activeCombatant,
|
||||
owner: combatant.isOwner,
|
||||
defeated: combatant.isDefeated,
|
||||
hidden: combatant.hidden,
|
||||
initiative: combatant.initiative,
|
||||
hasRolled: combatant.initiative !== null,
|
||||
hasResource: resource !== null,
|
||||
resource: resource,
|
||||
canPing: (combatant.sceneId === canvas.scene?.id) && game.user.hasPermission("PING_CANVAS"),
|
||||
playerCharacter: game.user?.character?.id === combatant.actor.id,
|
||||
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();
|
||||
|
||||
// Actor and Token status effects
|
||||
turn.effects = new Set();
|
||||
if ( combatant.token ) {
|
||||
combatant.token.effects.forEach(e => turn.effects.add(e));
|
||||
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);
|
||||
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 turn = {
|
||||
id: combatant.id,
|
||||
name: combatant.name,
|
||||
img: await this._getCombatantThumbnail(combatant),
|
||||
active: combatant.id === combat.system.activeCombatant,
|
||||
owner: combatant.isOwner,
|
||||
defeated: combatant.isDefeated,
|
||||
hidden: combatant.hidden,
|
||||
initiative: combatant.initiative,
|
||||
hasRolled: combatant.initiative !== null,
|
||||
hasResource: resource !== null,
|
||||
resource: resource,
|
||||
canPing: combatant.sceneId === canvas.scene?.id && game.user.hasPermission('PING_CANVAS'),
|
||||
playerCharacter: game.user?.character?.id === combatant.actor.id,
|
||||
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();
|
||||
|
||||
// Actor and Token status effects
|
||||
turn.effects = new Set();
|
||||
if (combatant.token) {
|
||||
combatant.token.effects.forEach(e => turn.effects.add(e));
|
||||
if (combatant.token.overlayEffect) turn.effects.add(combatant.token.overlayEffect);
|
||||
}
|
||||
}
|
||||
turns.push(turn);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
// Merge update data for rendering
|
||||
return foundry.utils.mergeObject(context, {
|
||||
round: combat.round,
|
||||
turn: combat.turn,
|
||||
turns: turns,
|
||||
control: combat.combatant?.players?.includes(game.user),
|
||||
fear: fear,
|
||||
round: combat.round,
|
||||
turn: combat.turn,
|
||||
turns: turns,
|
||||
control: combat.combatant?.players?.includes(game.user),
|
||||
fear: fear
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onFearUpdate = async () => {
|
||||
this.render(true);
|
||||
}
|
||||
};
|
||||
|
||||
async close(options){
|
||||
async close(options) {
|
||||
Hooks.off(socketEvent.DhpFearUpdate, this.onFearUpdate);
|
||||
|
||||
return super.close(options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,53 +1,53 @@
|
|||
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) {
|
||||
super(data, context);
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
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 },
|
||||
action: socketEvent.GMUpdate,
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
9402
package-lock.json
generated
9402
package-lock.json
generated
File diff suppressed because it is too large
Load diff
46
package.json
46
package.json
|
|
@ -1,22 +1,28 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"@yaireo/tagify": "^4.17.9",
|
||||
"gulp": "^5.0.0",
|
||||
"gulp-less": "^5.0.0",
|
||||
"rollup": "^4.40.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "concurrently \"rollup -c --watch\" \"node ../../../../FoundryDev/main.js --dataPath=../../../ --noupnp\" \"gulp\"",
|
||||
"start-test": "node ./resources/app/main.js --dataPath=./ && rollup -c --watch && gulp",
|
||||
"pushLDBtoYML": "node ./tools/pushLDBtoYML.mjs",
|
||||
"pullYMLtoLDB": "node ./tools/pullYMLtoLDB.mjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@foundryvtt/foundryvtt-cli": "^1.0.2",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"concurrently": "^8.2.2",
|
||||
"postcss": "^8.4.32",
|
||||
"rollup-plugin-postcss": "^4.0.2"
|
||||
}
|
||||
"dependencies": {
|
||||
"@yaireo/tagify": "^4.17.9",
|
||||
"gulp": "^5.0.0",
|
||||
"gulp-less": "^5.0.0",
|
||||
"rollup": "^4.40.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "concurrently \"rollup -c --watch\" \"node ../../../../FoundryDev/main.js --dataPath=../../../ --noupnp\" \"gulp\"",
|
||||
"start-test": "node ./resources/app/main.js --dataPath=./ && rollup -c --watch && gulp",
|
||||
"pushLDBtoYML": "node ./tools/pushLDBtoYML.mjs",
|
||||
"pullYMLtoLDB": "node ./tools/pullYMLtoLDB.mjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@foundryvtt/foundryvtt-cli": "^1.0.2",
|
||||
"@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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/** @type {import('postcss-load-config').Config} */
|
||||
const config = {
|
||||
plugins: []
|
||||
}
|
||||
|
||||
module.exports = config
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ export default {
|
|||
output: {
|
||||
file: 'build/daggerheart.js',
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
sourcemap: true
|
||||
},
|
||||
plugins: [
|
||||
postcss({
|
||||
config: {
|
||||
path: './postcss.config.js'
|
||||
},
|
||||
use: {
|
||||
use: {
|
||||
less: { javascriptEnabled: true }
|
||||
},
|
||||
extensions: ['.less'],
|
||||
|
|
@ -22,8 +22,8 @@ export default {
|
|||
}),
|
||||
commonjs({
|
||||
include: /node_modules/,
|
||||
requireReturnsDefault: 'auto',
|
||||
requireReturnsDefault: 'auto'
|
||||
}),
|
||||
resolve()
|
||||
],
|
||||
}
|
||||
]
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,30 +1,30 @@
|
|||
{
|
||||
"name": "Clank",
|
||||
"type": "ancestry",
|
||||
"_id": "AzKMOIpXnCSLLDEB",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"system": {
|
||||
"description": "<p><strong>Purposeful Design</strong>: Decide who made you and for what purpose. At character creation, choose one of your Experiences that best aligns with this purpose and gain a permanent +1 bonus to it.</p><p><strong>Efficient</strong>: When you take a short rest, you can choose a long rest move instead of a short rest move.</p>",
|
||||
"abilities": []
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 100000,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747990113503,
|
||||
"modifiedTime": 1747999445342,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!AzKMOIpXnCSLLDEB"
|
||||
"name": "Clank",
|
||||
"type": "ancestry",
|
||||
"_id": "AzKMOIpXnCSLLDEB",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"system": {
|
||||
"description": "<p><strong>Purposeful Design</strong>: Decide who made you and for what purpose. At character creation, choose one of your Experiences that best aligns with this purpose and gain a permanent +1 bonus to it.</p><p><strong>Efficient</strong>: When you take a short rest, you can choose a long rest move instead of a short rest move.</p>",
|
||||
"abilities": []
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 100000,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747990113503,
|
||||
"modifiedTime": 1747999445342,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!AzKMOIpXnCSLLDEB"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,44 @@
|
|||
{
|
||||
"name": "Make a Scene",
|
||||
"type": "feature",
|
||||
"_id": "Ddk0PAgwM4VLRbyY",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"system": {
|
||||
"actionType": "action",
|
||||
"featureType": {
|
||||
"type": "normal",
|
||||
"data": {
|
||||
"property": "spellcastingTrait",
|
||||
"max": 1,
|
||||
"numbers": {}
|
||||
}
|
||||
"name": "Make a Scene",
|
||||
"type": "feature",
|
||||
"_id": "Ddk0PAgwM4VLRbyY",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"system": {
|
||||
"actionType": "action",
|
||||
"featureType": {
|
||||
"type": "normal",
|
||||
"data": {
|
||||
"property": "spellcastingTrait",
|
||||
"max": 1,
|
||||
"numbers": {}
|
||||
}
|
||||
},
|
||||
"refreshData": null,
|
||||
"multiclass": null,
|
||||
"disabled": false,
|
||||
"description": "<p>Spend 3 Hope to temporarily Distract a target within Close range, giving them a -2 penalty to their Difficulty.</p>",
|
||||
"effects": {},
|
||||
"actions": [],
|
||||
"type": "class"
|
||||
},
|
||||
"refreshData": null,
|
||||
"multiclass": null,
|
||||
"disabled": false,
|
||||
"description": "<p>Spend 3 Hope to temporarily Distract a target within Close range, giving them a -2 penalty to their Difficulty.</p>",
|
||||
"effects": {},
|
||||
"actions": [],
|
||||
"type": "class"
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747991384366,
|
||||
"modifiedTime": 1747991421484,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!Ddk0PAgwM4VLRbyY"
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747991384366,
|
||||
"modifiedTime": 1747991421484,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!Ddk0PAgwM4VLRbyY"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,47 @@
|
|||
{
|
||||
"name": "Rally",
|
||||
"type": "feature",
|
||||
"_id": "8uORDWrXtNFzA00U",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"system": {
|
||||
"actionType": "action",
|
||||
"featureType": {
|
||||
"type": "normal",
|
||||
"data": {
|
||||
"property": "spellcastingTrait",
|
||||
"max": 1,
|
||||
"numbers": {},
|
||||
"value": "d6"
|
||||
}
|
||||
"name": "Rally",
|
||||
"type": "feature",
|
||||
"_id": "8uORDWrXtNFzA00U",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"system": {
|
||||
"actionType": "action",
|
||||
"featureType": {
|
||||
"type": "normal",
|
||||
"data": {
|
||||
"property": "spellcastingTrait",
|
||||
"max": 1,
|
||||
"numbers": {},
|
||||
"value": "d6"
|
||||
}
|
||||
},
|
||||
"refreshData": {
|
||||
"type": "session"
|
||||
},
|
||||
"multiclass": null,
|
||||
"disabled": false,
|
||||
"description": "<p>Once per session, describe how you rally the party and give yourself and each of your allies a Rally Die. At level 1, your Rally Die is a d6. A PC can spend their Rally Die to roll it, adding the result to their action roll, reaction roll, damage roll, or to clear a number of Stress equal to the result. At the end of each session, clear all unspent Rally Dice.</p><p>At level 5, your Rally Die increases to a d8.</p>",
|
||||
"effects": {},
|
||||
"actions": [],
|
||||
"type": "class"
|
||||
},
|
||||
"refreshData": {
|
||||
"type": "session"
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"multiclass": null,
|
||||
"disabled": false,
|
||||
"description": "<p>Once per session, describe how you rally the party and give yourself and each of your allies a Rally Die. At level 1, your Rally Die is a d6. A PC can spend their Rally Die to roll it, adding the result to their action roll, reaction roll, damage roll, or to clear a number of Stress equal to the result. At the end of each session, clear all unspent Rally Dice.</p><p>At level 5, your Rally Die increases to a d8.</p>",
|
||||
"effects": {},
|
||||
"actions": [],
|
||||
"type": "class"
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747991484460,
|
||||
"modifiedTime": 1747991546148,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!8uORDWrXtNFzA00U"
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747991484460,
|
||||
"modifiedTime": 1747991546148,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!8uORDWrXtNFzA00U"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,104 +1,93 @@
|
|||
{
|
||||
"name": "Bard",
|
||||
"type": "class",
|
||||
"_id": "yKicceU4LesCgKwF",
|
||||
"img": "systems/daggerheart/assets/icons/classes/bard.png",
|
||||
"system": {
|
||||
"domains": [
|
||||
"grace",
|
||||
"codex"
|
||||
],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
},
|
||||
"evasion": 10,
|
||||
"features": [
|
||||
{
|
||||
"name": "Make a Scene",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"uuid": "Compendium.daggerheart.class-features.Item.Ddk0PAgwM4VLRbyY"
|
||||
},
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Rally",
|
||||
"uuid": "Compendium.daggerheart.class-features.Item.8uORDWrXtNFzA00U"
|
||||
}
|
||||
],
|
||||
"subclasses": [
|
||||
{
|
||||
"name": "Troubadour",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"uuid": "Compendium.daggerheart.subclasses.Item.T1iBO8i0xRF5c8Q2"
|
||||
},
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Wordsmith",
|
||||
"uuid": "Compendium.daggerheart.subclasses.Item.FXT65YDVWFy85EI0"
|
||||
}
|
||||
],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": {
|
||||
"title": "",
|
||||
"name": "Bard",
|
||||
"type": "class",
|
||||
"_id": "yKicceU4LesCgKwF",
|
||||
"img": "systems/daggerheart/assets/icons/classes/bard.png",
|
||||
"system": {
|
||||
"domains": ["grace", "codex"],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
},
|
||||
"evasion": 10,
|
||||
"features": [
|
||||
{
|
||||
"name": "Make a Scene",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"uuid": "Compendium.daggerheart.class-features.Item.Ddk0PAgwM4VLRbyY"
|
||||
},
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Rally",
|
||||
"uuid": "Compendium.daggerheart.class-features.Item.8uORDWrXtNFzA00U"
|
||||
}
|
||||
],
|
||||
"subclasses": [
|
||||
{
|
||||
"name": "Troubadour",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"uuid": "Compendium.daggerheart.subclasses.Item.T1iBO8i0xRF5c8Q2"
|
||||
},
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Wordsmith",
|
||||
"uuid": "Compendium.daggerheart.subclasses.Item.FXT65YDVWFy85EI0"
|
||||
}
|
||||
],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": {
|
||||
"title": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {
|
||||
"clothes": "",
|
||||
"eyes": "",
|
||||
"body": "",
|
||||
"color": "",
|
||||
"attitude": ""
|
||||
},
|
||||
"backgroundQuestions": ["", "", ""],
|
||||
"connections": ["", "", ""]
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {
|
||||
"clothes": "",
|
||||
"eyes": "",
|
||||
"body": "",
|
||||
"color": "",
|
||||
"attitude": ""
|
||||
},
|
||||
"backgroundQuestions": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"connections": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946810798,
|
||||
"modifiedTime": 1747991996135,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!yKicceU4LesCgKwF"
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946810798,
|
||||
"modifiedTime": 1747991996135,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!yKicceU4LesCgKwF"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +1,62 @@
|
|||
{
|
||||
"name": "Druid",
|
||||
"type": "class",
|
||||
"_id": "HEh27jDQCJmnPsXH",
|
||||
"img": "systems/daggerheart/assets/icons/classes/druid.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
"name": "Druid",
|
||||
"type": "class",
|
||||
"_id": "HEh27jDQCJmnPsXH",
|
||||
"img": "systems/daggerheart/assets/icons/classes/druid.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": ["", "", ""],
|
||||
"connections": ["", "", ""]
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"connections": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946822837,
|
||||
"modifiedTime": 1747946826150,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946822837,
|
||||
"modifiedTime": 1747946826150,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!HEh27jDQCJmnPsXH"
|
||||
"_key": "!items!HEh27jDQCJmnPsXH"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +1,62 @@
|
|||
{
|
||||
"name": "Fighter",
|
||||
"type": "class",
|
||||
"_id": "HPzaWaZBc6RvElKd",
|
||||
"img": "systems/daggerheart/assets/icons/classes/fighter.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
"name": "Fighter",
|
||||
"type": "class",
|
||||
"_id": "HPzaWaZBc6RvElKd",
|
||||
"img": "systems/daggerheart/assets/icons/classes/fighter.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": ["", "", ""],
|
||||
"connections": ["", "", ""]
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"connections": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946839346,
|
||||
"modifiedTime": 1747946842033,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946839346,
|
||||
"modifiedTime": 1747946842033,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!HPzaWaZBc6RvElKd"
|
||||
"_key": "!items!HPzaWaZBc6RvElKd"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +1,62 @@
|
|||
{
|
||||
"name": "Guardian",
|
||||
"type": "class",
|
||||
"_id": "hyfigmrAoLxFPOW2",
|
||||
"img": "systems/daggerheart/assets/icons/classes/guardian.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
"name": "Guardian",
|
||||
"type": "class",
|
||||
"_id": "hyfigmrAoLxFPOW2",
|
||||
"img": "systems/daggerheart/assets/icons/classes/guardian.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": ["", "", ""],
|
||||
"connections": ["", "", ""]
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"connections": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946853583,
|
||||
"modifiedTime": 1747946858579,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946853583,
|
||||
"modifiedTime": 1747946858579,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!hyfigmrAoLxFPOW2"
|
||||
"_key": "!items!hyfigmrAoLxFPOW2"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +1,62 @@
|
|||
{
|
||||
"name": "Ranger",
|
||||
"type": "class",
|
||||
"_id": "XoUsU9sCxEq8t3We",
|
||||
"img": "systems/daggerheart/assets/icons/classes/ranger.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
"name": "Ranger",
|
||||
"type": "class",
|
||||
"_id": "XoUsU9sCxEq8t3We",
|
||||
"img": "systems/daggerheart/assets/icons/classes/ranger.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": ["", "", ""],
|
||||
"connections": ["", "", ""]
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"connections": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946878680,
|
||||
"modifiedTime": 1747946882593,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946878680,
|
||||
"modifiedTime": 1747946882593,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!XoUsU9sCxEq8t3We"
|
||||
"_key": "!items!XoUsU9sCxEq8t3We"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +1,62 @@
|
|||
{
|
||||
"name": "Rogue",
|
||||
"type": "class",
|
||||
"_id": "V1a5AKCLe8qtoPlA",
|
||||
"img": "systems/daggerheart/assets/icons/classes/rogue.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
"name": "Rogue",
|
||||
"type": "class",
|
||||
"_id": "V1a5AKCLe8qtoPlA",
|
||||
"img": "systems/daggerheart/assets/icons/classes/rogue.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": ["", "", ""],
|
||||
"connections": ["", "", ""]
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"connections": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946902620,
|
||||
"modifiedTime": 1747946906032,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946902620,
|
||||
"modifiedTime": 1747946906032,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!V1a5AKCLe8qtoPlA"
|
||||
"_key": "!items!V1a5AKCLe8qtoPlA"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +1,62 @@
|
|||
{
|
||||
"name": "Seraph",
|
||||
"type": "class",
|
||||
"_id": "qW7yLIe87vd5bbto",
|
||||
"img": "systems/daggerheart/assets/icons/classes/seraph.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
"name": "Seraph",
|
||||
"type": "class",
|
||||
"_id": "qW7yLIe87vd5bbto",
|
||||
"img": "systems/daggerheart/assets/icons/classes/seraph.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": ["", "", ""],
|
||||
"connections": ["", "", ""]
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"connections": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946916585,
|
||||
"modifiedTime": 1747946919635,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946916585,
|
||||
"modifiedTime": 1747946919635,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!qW7yLIe87vd5bbto"
|
||||
"_key": "!items!qW7yLIe87vd5bbto"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +1,62 @@
|
|||
{
|
||||
"name": "Sorcerer",
|
||||
"type": "class",
|
||||
"_id": "aacMxI9mOTmLO4cj",
|
||||
"img": "systems/daggerheart/assets/icons/classes/sorcerer.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
"name": "Sorcerer",
|
||||
"type": "class",
|
||||
"_id": "aacMxI9mOTmLO4cj",
|
||||
"img": "systems/daggerheart/assets/icons/classes/sorcerer.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": ["", "", ""],
|
||||
"connections": ["", "", ""]
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"connections": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946940010,
|
||||
"modifiedTime": 1747946943869,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946940010,
|
||||
"modifiedTime": 1747946943869,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!aacMxI9mOTmLO4cj"
|
||||
"_key": "!items!aacMxI9mOTmLO4cj"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +1,62 @@
|
|||
{
|
||||
"name": "Warlock",
|
||||
"type": "class",
|
||||
"_id": "kSSIqmgxFTm1Xr9s",
|
||||
"img": "systems/daggerheart/assets/icons/classes/warlock.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
"name": "Warlock",
|
||||
"type": "class",
|
||||
"_id": "kSSIqmgxFTm1Xr9s",
|
||||
"img": "systems/daggerheart/assets/icons/classes/warlock.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": ["", "", ""],
|
||||
"connections": ["", "", ""]
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"connections": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946952119,
|
||||
"modifiedTime": 1747946955843,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946952119,
|
||||
"modifiedTime": 1747946955843,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!kSSIqmgxFTm1Xr9s"
|
||||
"_key": "!items!kSSIqmgxFTm1Xr9s"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +1,62 @@
|
|||
{
|
||||
"name": "Warrior",
|
||||
"type": "class",
|
||||
"_id": "ishqAXCT8xLgEbBp",
|
||||
"img": "systems/daggerheart/assets/icons/classes/warrior.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
"name": "Warrior",
|
||||
"type": "class",
|
||||
"_id": "ishqAXCT8xLgEbBp",
|
||||
"img": "systems/daggerheart/assets/icons/classes/warrior.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": ["", "", ""],
|
||||
"connections": ["", "", ""]
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"connections": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946965065,
|
||||
"modifiedTime": 1747946967544,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946965065,
|
||||
"modifiedTime": 1747946967544,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!ishqAXCT8xLgEbBp"
|
||||
"_key": "!items!ishqAXCT8xLgEbBp"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +1,62 @@
|
|||
{
|
||||
"name": "Wizard",
|
||||
"type": "class",
|
||||
"_id": "uhj2mZPOC8nbIMTy",
|
||||
"img": "systems/daggerheart/assets/icons/classes/wizard.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
"name": "Wizard",
|
||||
"type": "class",
|
||||
"_id": "uhj2mZPOC8nbIMTy",
|
||||
"img": "systems/daggerheart/assets/icons/classes/wizard.png",
|
||||
"system": {
|
||||
"domains": [],
|
||||
"classItems": [],
|
||||
"damageThresholds": {
|
||||
"minor": 0,
|
||||
"major": 0,
|
||||
"severe": 0
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": ["", "", ""],
|
||||
"connections": ["", "", ""]
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"evasion": 0,
|
||||
"features": [],
|
||||
"subclasses": [],
|
||||
"inventory": {
|
||||
"take": [],
|
||||
"choiceA": [],
|
||||
"choiceB": [],
|
||||
"extra": null
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"characterGuide": {
|
||||
"suggestedTraits": {
|
||||
"agility": 0,
|
||||
"strength": 0,
|
||||
"finesse": 0,
|
||||
"instinct": 0,
|
||||
"presence": 0,
|
||||
"knowledge": 0
|
||||
},
|
||||
"suggestedPrimaryWeapon": null,
|
||||
"suggestedSecondaryWeapon": null,
|
||||
"suggestedArmor": null,
|
||||
"characterDescription": {},
|
||||
"backgroundQuestions": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"connections": [
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946791380,
|
||||
"modifiedTime": 1747946799247,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"multiclass": null,
|
||||
"description": ""
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747946791380,
|
||||
"modifiedTime": 1747946799247,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!uhj2mZPOC8nbIMTy"
|
||||
"_key": "!items!uhj2mZPOC8nbIMTy"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,36 @@
|
|||
{
|
||||
"name": "Highborne",
|
||||
"type": "community",
|
||||
"_id": "8AcV556QwoIzkkea",
|
||||
"img": "systems/daggerheart/assets/icons/communities/highborne.png",
|
||||
"system": {
|
||||
"description": "<p>Being part of a highborne community means you're accustomed to life of elegance, opulence, and prestige within the upper echelons of society. Traditionally, members of a highborne community possess incredible material wealth. While this can take a variety of forms depending on the community—including gold and other minerals, land, or controlling the means of production—this status always comes with power and influence. Highborne place great value on titles and possessions, and there is little social mobility within their ranks. Members of a highborne community often control the political and economic status of the areas in which they live due to their ability to influence people and the economy with their substantial wealth. The health and safety of the less affluent people who live in these locations often hinges on the ability of this highborne ruling class to prioritize the well-being of their subjects over profit.</p><p><em>Highborne are often amiable, candid, conniving, enterprising, ostentatious, and unflappable.</em></p>",
|
||||
"abilities": [
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Privilege",
|
||||
"uuid": "Compendium.world.community-features.Item.WoMZCTnDcK8GPSh1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747940320728,
|
||||
"modifiedTime": 1747990568291,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!8AcV556QwoIzkkea"
|
||||
"name": "Highborne",
|
||||
"type": "community",
|
||||
"_id": "8AcV556QwoIzkkea",
|
||||
"img": "systems/daggerheart/assets/icons/communities/highborne.png",
|
||||
"system": {
|
||||
"description": "<p>Being part of a highborne community means you're accustomed to life of elegance, opulence, and prestige within the upper echelons of society. Traditionally, members of a highborne community possess incredible material wealth. While this can take a variety of forms depending on the community—including gold and other minerals, land, or controlling the means of production—this status always comes with power and influence. Highborne place great value on titles and possessions, and there is little social mobility within their ranks. Members of a highborne community often control the political and economic status of the areas in which they live due to their ability to influence people and the economy with their substantial wealth. The health and safety of the less affluent people who live in these locations often hinges on the ability of this highborne ruling class to prioritize the well-being of their subjects over profit.</p><p><em>Highborne are often amiable, candid, conniving, enterprising, ostentatious, and unflappable.</em></p>",
|
||||
"abilities": [
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Privilege",
|
||||
"uuid": "Compendium.world.community-features.Item.WoMZCTnDcK8GPSh1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747940320728,
|
||||
"modifiedTime": 1747990568291,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!8AcV556QwoIzkkea"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,36 @@
|
|||
{
|
||||
"name": "Loreborne",
|
||||
"type": "community",
|
||||
"_id": "fgJHuCdoyXX4Q84O",
|
||||
"img": "systems/daggerheart/assets/icons/communities/loreborne.png",
|
||||
"system": {
|
||||
"description": "<p>Being part of a loreborne community means you’re from a society that favors strong academic or political prowess. Loreborne communities highly value knowledge, frequently in the form of historical preservation, political advancement, scientific study, skill development, or lore and mythology compilation. Most members of these communities research in institutions built in bastions of civilization, while some eclectic few thrive in gathering information from the natural world. Some may be isolationists, operating in smaller enclaves, schools, or guilds and following their own unique ethos. Others still wield their knowledge on a larger scale, making deft political maneuvers across governmental landscapes.</p><p><em>Loreborne are often direct, eloquent, inquisitive, patient,</em></p><p>rhapsodic, and witty.</p>",
|
||||
"abilities": [
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Well-Read",
|
||||
"uuid": "Compendium.world.community-features.Item.MUfVlf8hoJ3HZidv"
|
||||
}
|
||||
]
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747940300210,
|
||||
"modifiedTime": 1747990671092,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!fgJHuCdoyXX4Q84O"
|
||||
"name": "Loreborne",
|
||||
"type": "community",
|
||||
"_id": "fgJHuCdoyXX4Q84O",
|
||||
"img": "systems/daggerheart/assets/icons/communities/loreborne.png",
|
||||
"system": {
|
||||
"description": "<p>Being part of a loreborne community means you’re from a society that favors strong academic or political prowess. Loreborne communities highly value knowledge, frequently in the form of historical preservation, political advancement, scientific study, skill development, or lore and mythology compilation. Most members of these communities research in institutions built in bastions of civilization, while some eclectic few thrive in gathering information from the natural world. Some may be isolationists, operating in smaller enclaves, schools, or guilds and following their own unique ethos. Others still wield their knowledge on a larger scale, making deft political maneuvers across governmental landscapes.</p><p><em>Loreborne are often direct, eloquent, inquisitive, patient,</em></p><p>rhapsodic, and witty.</p>",
|
||||
"abilities": [
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Well-Read",
|
||||
"uuid": "Compendium.world.community-features.Item.MUfVlf8hoJ3HZidv"
|
||||
}
|
||||
]
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747940300210,
|
||||
"modifiedTime": 1747990671092,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!fgJHuCdoyXX4Q84O"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,36 @@
|
|||
{
|
||||
"name": "Orderborne",
|
||||
"type": "community",
|
||||
"_id": "Cg39GoSa6lxhXndW",
|
||||
"img": "systems/daggerheart/assets/icons/communities/orderborne.png",
|
||||
"system": {
|
||||
"description": "<p>Being part of an orderborne community means you’re from a collective that focuses on discipline or faith, and you uphold a set of principles that reflect your experience there. Orderborne are frequently some of the most powerful among the surrounding communities.</p><p>By aligning the members of their society around a common value or goal, such as a god, doctrine, ethos, or even a shared business or trade, the ruling bodies of these enclaves are able to mobilize larger populations with less effort.</p><p>While orderborne communities take a variety of forms—some even profoundly pacifistic—perhaps the most feared are those that structure themselves around military prowess. In such a case, it’s not uncommon for orderborne to provide soldiers for hire to other cities or countries.</p><p><em>Orderborne are often ambitious, benevolent, pensive, prudent, sardonic, and stoic.</em></p>",
|
||||
"abilities": [
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Dedicated",
|
||||
"uuid": "Compendium.world.community-features.Item.b7LmL7ti1gL5kfGq"
|
||||
}
|
||||
]
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747940332147,
|
||||
"modifiedTime": 1747990820386,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!Cg39GoSa6lxhXndW"
|
||||
"name": "Orderborne",
|
||||
"type": "community",
|
||||
"_id": "Cg39GoSa6lxhXndW",
|
||||
"img": "systems/daggerheart/assets/icons/communities/orderborne.png",
|
||||
"system": {
|
||||
"description": "<p>Being part of an orderborne community means you’re from a collective that focuses on discipline or faith, and you uphold a set of principles that reflect your experience there. Orderborne are frequently some of the most powerful among the surrounding communities.</p><p>By aligning the members of their society around a common value or goal, such as a god, doctrine, ethos, or even a shared business or trade, the ruling bodies of these enclaves are able to mobilize larger populations with less effort.</p><p>While orderborne communities take a variety of forms—some even profoundly pacifistic—perhaps the most feared are those that structure themselves around military prowess. In such a case, it’s not uncommon for orderborne to provide soldiers for hire to other cities or countries.</p><p><em>Orderborne are often ambitious, benevolent, pensive, prudent, sardonic, and stoic.</em></p>",
|
||||
"abilities": [
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Dedicated",
|
||||
"uuid": "Compendium.world.community-features.Item.b7LmL7ti1gL5kfGq"
|
||||
}
|
||||
]
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747940332147,
|
||||
"modifiedTime": 1747990820386,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!Cg39GoSa6lxhXndW"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,36 @@
|
|||
{
|
||||
"name": "Ridgeborne",
|
||||
"type": "community",
|
||||
"_id": "DAQoNvVlc9w7NmZd",
|
||||
"img": "systems/daggerheart/assets/icons/communities/ridgeborne.png",
|
||||
"system": {
|
||||
"description": "<p>Being part of a ridgeborne community means you’ve called the rocky peaks and sharp cliffs of the mountainside home. Those who’ve lived in the mountains often consider themselves hardier than most because they’ve thrived among the most dangerous terrain many continents have to offer. These groups are adept at adaptation, developing unique technologies and equipment to move both people and products across difficult terrain. As such, ridgeborne grow up scrambling and climbing, making them sturdy and strong-willed. Ridgeborne localities appear in a variety of forms—some cities carve out entire cliff faces, others construct castles of stone, and still more live in small homes on windblown peaks. Outside forces often struggle to attack ridgeborne groups, as the small militias and large military forces of the mountains are adept at utilizing their high-ground advantage.</p><p><em>Ridgeborne are often bold, hardy, indomitable, loyal, reserved, and stubborn.</em></p>",
|
||||
"abilities": [
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Steady",
|
||||
"uuid": "Compendium.world.community-features.Item.hKGv54dst9crq3Sw"
|
||||
}
|
||||
]
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747940346633,
|
||||
"modifiedTime": 1747990891669,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!DAQoNvVlc9w7NmZd"
|
||||
"name": "Ridgeborne",
|
||||
"type": "community",
|
||||
"_id": "DAQoNvVlc9w7NmZd",
|
||||
"img": "systems/daggerheart/assets/icons/communities/ridgeborne.png",
|
||||
"system": {
|
||||
"description": "<p>Being part of a ridgeborne community means you’ve called the rocky peaks and sharp cliffs of the mountainside home. Those who’ve lived in the mountains often consider themselves hardier than most because they’ve thrived among the most dangerous terrain many continents have to offer. These groups are adept at adaptation, developing unique technologies and equipment to move both people and products across difficult terrain. As such, ridgeborne grow up scrambling and climbing, making them sturdy and strong-willed. Ridgeborne localities appear in a variety of forms—some cities carve out entire cliff faces, others construct castles of stone, and still more live in small homes on windblown peaks. Outside forces often struggle to attack ridgeborne groups, as the small militias and large military forces of the mountains are adept at utilizing their high-ground advantage.</p><p><em>Ridgeborne are often bold, hardy, indomitable, loyal, reserved, and stubborn.</em></p>",
|
||||
"abilities": [
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Steady",
|
||||
"uuid": "Compendium.world.community-features.Item.hKGv54dst9crq3Sw"
|
||||
}
|
||||
]
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747940346633,
|
||||
"modifiedTime": 1747990891669,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!DAQoNvVlc9w7NmZd"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,36 @@
|
|||
{
|
||||
"name": "Seaborne",
|
||||
"type": "community",
|
||||
"_id": "ivrXToGxyuVdqZtG",
|
||||
"img": "systems/daggerheart/assets/icons/communities/seaborne.png",
|
||||
"system": {
|
||||
"description": "<p>Being part of a seaborne community means you lived on or near a large body of water. Seaborne communities are built, both physically and culturally, around the specific waters they call home.</p><p>Some of these groups live along the shore, constructing ports for locals and travelers alike. These harbors function as centers of commerce, tourist attractions, or even just a safe place to lay down one’s head after weeks of travel. Other seaborne live on the water in small boats or large ships, with the idea of “home” comprising a ship and its crew, rather than any one landmass.</p><p>No matter their exact location, seaborne communities are closely tied to the ocean tides and the creatures who inhabit them. Seaborne learn to fish at a young age, and train from birth to hold their breath and swim in even the most tumultuous waters. Individuals from these groups are highly sought after for their sailing skills, and many become captains of vessels, whether within their own community, working for another, or even at the helm of a powerful naval operation.<br><em><br>Seaborne are often candid, cooperative, exuberant, fierce, resolute, and weathered.</em></p>",
|
||||
"abilities": [
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Know the Tide",
|
||||
"uuid": "Compendium.world.community-features.Item.coBcBEFpXgtxD1Jt"
|
||||
}
|
||||
]
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747940375520,
|
||||
"modifiedTime": 1747990980804,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!ivrXToGxyuVdqZtG"
|
||||
"name": "Seaborne",
|
||||
"type": "community",
|
||||
"_id": "ivrXToGxyuVdqZtG",
|
||||
"img": "systems/daggerheart/assets/icons/communities/seaborne.png",
|
||||
"system": {
|
||||
"description": "<p>Being part of a seaborne community means you lived on or near a large body of water. Seaborne communities are built, both physically and culturally, around the specific waters they call home.</p><p>Some of these groups live along the shore, constructing ports for locals and travelers alike. These harbors function as centers of commerce, tourist attractions, or even just a safe place to lay down one’s head after weeks of travel. Other seaborne live on the water in small boats or large ships, with the idea of “home” comprising a ship and its crew, rather than any one landmass.</p><p>No matter their exact location, seaborne communities are closely tied to the ocean tides and the creatures who inhabit them. Seaborne learn to fish at a young age, and train from birth to hold their breath and swim in even the most tumultuous waters. Individuals from these groups are highly sought after for their sailing skills, and many become captains of vessels, whether within their own community, working for another, or even at the helm of a powerful naval operation.<br><em><br>Seaborne are often candid, cooperative, exuberant, fierce, resolute, and weathered.</em></p>",
|
||||
"abilities": [
|
||||
{
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
"name": "Know the Tide",
|
||||
"uuid": "Compendium.world.community-features.Item.coBcBEFpXgtxD1Jt"
|
||||
}
|
||||
]
|
||||
},
|
||||
"effects": [],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"ownership": {
|
||||
"default": 0,
|
||||
"NqO2eQGMjrvUO6v9": 3
|
||||
},
|
||||
"flags": {},
|
||||
"_stats": {
|
||||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"systemId": "daggerheart",
|
||||
"systemVersion": "0.0.1",
|
||||
"createdTime": 1747940375520,
|
||||
"modifiedTime": 1747990980804,
|
||||
"lastModifiedBy": "NqO2eQGMjrvUO6v9"
|
||||
},
|
||||
"_key": "!items!ivrXToGxyuVdqZtG"
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue