mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-04-21 23:13:39 +02:00
Merged with v14-Dev
This commit is contained in:
commit
4332a1ba7a
613 changed files with 4618 additions and 2996 deletions
|
|
@ -246,6 +246,11 @@ Hooks.once('init', () => {
|
||||||
return handlebarsRegistration();
|
return handlebarsRegistration();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Hooks.on('i18nInit', () => {
|
||||||
|
// Setup homebrew resources
|
||||||
|
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).refreshConfig();
|
||||||
|
});
|
||||||
|
|
||||||
Hooks.on('setup', () => {
|
Hooks.on('setup', () => {
|
||||||
CONFIG.statusEffects = [
|
CONFIG.statusEffects = [
|
||||||
...CONFIG.statusEffects.filter(x => !['dead', 'unconscious'].includes(x.id)),
|
...CONFIG.statusEffects.filter(x => !['dead', 'unconscious'].includes(x.id)),
|
||||||
|
|
|
||||||
57
lang/en.json
57
lang/en.json
|
|
@ -77,6 +77,15 @@
|
||||||
"invalidDrop": "You can only drop Actor entities to summon.",
|
"invalidDrop": "You can only drop Actor entities to summon.",
|
||||||
"chatMessageTitle": "Test2",
|
"chatMessageTitle": "Test2",
|
||||||
"chatMessageHeaderTitle": "Summoning"
|
"chatMessageHeaderTitle": "Summoning"
|
||||||
|
},
|
||||||
|
"transform": {
|
||||||
|
"name": "Transform",
|
||||||
|
"tooltip": "Transform one actor into another",
|
||||||
|
"noTransformActor": "There is no assigned actor to transform into",
|
||||||
|
"transformActorMissing": "The assigned actor to transform into does not exist. It was probably deleted or moved in/out of a compendium",
|
||||||
|
"canvasError": "There is no active scene.",
|
||||||
|
"prototypeError": "You can only use a transform action from a Token",
|
||||||
|
"actorLinkError": "You cannot transform a token with Actor Link set to true"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Config": {
|
"Config": {
|
||||||
|
|
@ -132,6 +141,12 @@
|
||||||
},
|
},
|
||||||
"summon": {
|
"summon": {
|
||||||
"dropSummonsHere": "Drop Summons Here"
|
"dropSummonsHere": "Drop Summons Here"
|
||||||
|
},
|
||||||
|
"transform": {
|
||||||
|
"dropTransformHere": "Drop Transform Here",
|
||||||
|
"actorIsMissing": "The linked actor is missing. You should delete this link.",
|
||||||
|
"clearHitPoints": "Clear Hitpoints",
|
||||||
|
"clearStress": "Clear Stress"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -1060,6 +1075,10 @@
|
||||||
"fear": "Fear",
|
"fear": "Fear",
|
||||||
"spotlight": "Spotlight"
|
"spotlight": "Spotlight"
|
||||||
},
|
},
|
||||||
|
"DaggerheartDiceAnimationEvents": {
|
||||||
|
"critical": { "name": "Critical" },
|
||||||
|
"higher": { "name": "Highest Roll" }
|
||||||
|
},
|
||||||
"DamageType": {
|
"DamageType": {
|
||||||
"physical": {
|
"physical": {
|
||||||
"name": "Physical",
|
"name": "Physical",
|
||||||
|
|
@ -2293,6 +2312,7 @@
|
||||||
"identify": "Identity",
|
"identify": "Identity",
|
||||||
"imagePath": "Image Path",
|
"imagePath": "Image Path",
|
||||||
"inactiveEffects": "Inactive Effects",
|
"inactiveEffects": "Inactive Effects",
|
||||||
|
"initial": "Initial",
|
||||||
"inventory": "Inventory",
|
"inventory": "Inventory",
|
||||||
"itemResource": "Item Resource",
|
"itemResource": "Item Resource",
|
||||||
"itemQuantity": "Item Quantity",
|
"itemQuantity": "Item Quantity",
|
||||||
|
|
@ -2320,6 +2340,7 @@
|
||||||
"plurial": "Players"
|
"plurial": "Players"
|
||||||
},
|
},
|
||||||
"portrait": "Portrait",
|
"portrait": "Portrait",
|
||||||
|
"preview": "Preview",
|
||||||
"proficiency": "Proficiency",
|
"proficiency": "Proficiency",
|
||||||
"quantity": "Quantity",
|
"quantity": "Quantity",
|
||||||
"range": "Range",
|
"range": "Range",
|
||||||
|
|
@ -2660,6 +2681,14 @@
|
||||||
"title": "Triggers"
|
"title": "Triggers"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Metagaming": {
|
||||||
|
"FIELDS": {
|
||||||
|
"hideObserverPermissionInChat": {
|
||||||
|
"label": "Hide Chat Info From Players",
|
||||||
|
"hint": "Information such as hit/miss on attack rolls against adversaries will be hidden"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Homebrew": {
|
"Homebrew": {
|
||||||
"newDowntimeMove": "Downtime Move",
|
"newDowntimeMove": "Downtime Move",
|
||||||
"downtimeMove": "Downtime Move",
|
"downtimeMove": "Downtime Move",
|
||||||
|
|
@ -2674,6 +2703,8 @@
|
||||||
"resetMovesText": "Are you sure you want to reset?",
|
"resetMovesText": "Are you sure you want to reset?",
|
||||||
"deleteItemTitle": "Delete Homebrew Item",
|
"deleteItemTitle": "Delete Homebrew Item",
|
||||||
"deleteItemText": "Are you sure you want to delete the item?",
|
"deleteItemText": "Are you sure you want to delete the item?",
|
||||||
|
"deleteResourceTitle": "Delete Homebrew Resource",
|
||||||
|
"deleteResourceText": "Are you sure you want to delete the resource?",
|
||||||
"FIELDS": {
|
"FIELDS": {
|
||||||
"maxFear": { "label": "Max Fear" },
|
"maxFear": { "label": "Max Fear" },
|
||||||
"maxHope": { "label": "Max Hope" },
|
"maxHope": { "label": "Max Hope" },
|
||||||
|
|
@ -2682,6 +2713,13 @@
|
||||||
"label": "Max Cards in Loadout",
|
"label": "Max Cards in Loadout",
|
||||||
"hint": "Set to blank or 0 for unlimited maximum"
|
"hint": "Set to blank or 0 for unlimited maximum"
|
||||||
},
|
},
|
||||||
|
"resources": {
|
||||||
|
"resources": {
|
||||||
|
"value": { "label": "Icon" },
|
||||||
|
"isIcon": { "label": "Font Awesome Icon" },
|
||||||
|
"noColorFilter": { "label": "Disable Color Filter" }
|
||||||
|
}
|
||||||
|
},
|
||||||
"maxDomains": { "label": "Max Class Domains", "hint": "Max domains you can set on a class" }
|
"maxDomains": { "label": "Max Class Domains", "hint": "Max domains you can set on a class" }
|
||||||
},
|
},
|
||||||
"currency": {
|
"currency": {
|
||||||
|
|
@ -2710,6 +2748,13 @@
|
||||||
"adversaryType": {
|
"adversaryType": {
|
||||||
"title": "Custom Adversary Types",
|
"title": "Custom Adversary Types",
|
||||||
"newType": "Adversary Type"
|
"newType": "Adversary Type"
|
||||||
|
},
|
||||||
|
"resources": {
|
||||||
|
"typeTitle": "{type} Resources",
|
||||||
|
"filledIcon": "Filled Icon",
|
||||||
|
"emptyIcon": "Empty Icon",
|
||||||
|
"resourceIdentifier": "Resource Identifier",
|
||||||
|
"setResourceIdentifier": "Set Resource Identifier"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Menu": {
|
"Menu": {
|
||||||
|
|
@ -2719,6 +2764,11 @@
|
||||||
"label": "Configure Automation",
|
"label": "Configure Automation",
|
||||||
"hint": "Various settings automating resource management and more"
|
"hint": "Various settings automating resource management and more"
|
||||||
},
|
},
|
||||||
|
"metagaming": {
|
||||||
|
"name": "Metagaming Settings",
|
||||||
|
"label": "Configure Metagaming",
|
||||||
|
"hint": "Various settings controlling the flow of information to players"
|
||||||
|
},
|
||||||
"homebrew": {
|
"homebrew": {
|
||||||
"name": "Homebrew Settings",
|
"name": "Homebrew Settings",
|
||||||
"label": "Configure Homebrew",
|
"label": "Configure Homebrew",
|
||||||
|
|
@ -2744,7 +2794,12 @@
|
||||||
"colorset": "Theme",
|
"colorset": "Theme",
|
||||||
"material": "Material",
|
"material": "Material",
|
||||||
"system": "Dice Preset",
|
"system": "Dice Preset",
|
||||||
"font": "Font"
|
"font": "Font",
|
||||||
|
"critical": "Duality Critical Animation",
|
||||||
|
"diceAppearance": "Dice Appearance",
|
||||||
|
"animations": "Animations",
|
||||||
|
"defaultAnimations": "Set Animations As Player Defaults",
|
||||||
|
"previewAnimation": "Preview Animation"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"variantRules": {
|
"variantRules": {
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ export default class DhCompanionLevelUp extends BaseLevelUp {
|
||||||
break;
|
break;
|
||||||
case 'summary':
|
case 'summary':
|
||||||
const levelKeys = Object.keys(this.levelup.levels);
|
const levelKeys = Object.keys(this.levelup.levels);
|
||||||
const actorDamageDice = this.actor.system.attack.damage.parts[0].value.dice;
|
const actorDamageDice = this.actor.system.attack.damage.parts.hitPoints.value.dice;
|
||||||
const actorRange = this.actor.system.attack.range;
|
const actorRange = this.actor.system.attack.range;
|
||||||
|
|
||||||
let achievementExperiences = [];
|
let achievementExperiences = [];
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
export { default as DhAppearanceSettings } from './appearanceSettings.mjs';
|
export { default as DhAppearanceSettings } from './appearanceSettings.mjs';
|
||||||
export { default as DhAutomationSettings } from './automationSettings.mjs';
|
export { default as DhAutomationSettings } from './automationSettings.mjs';
|
||||||
export { default as DhHomebrewSettings } from './homebrewSettings.mjs';
|
export { default as DhHomebrewSettings } from './homebrewSettings.mjs';
|
||||||
|
export { default as DhMetagamingSettings } from './metagamingSettings.mjs';
|
||||||
export { default as DhVariantRuleSettings } from './variantRuleSettings.mjs';
|
export { default as DhVariantRuleSettings } from './variantRuleSettings.mjs';
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
tag: 'form',
|
tag: 'form',
|
||||||
id: 'daggerheart-appearance-settings',
|
id: 'daggerheart-appearance-settings',
|
||||||
classes: ['daggerheart', 'dialog', 'dh-style', 'setting'],
|
classes: ['daggerheart', 'dialog', 'dh-style', 'setting', 'appearance-settings'],
|
||||||
position: { width: '600', height: 'auto' },
|
position: { width: '600', height: 'auto' },
|
||||||
window: {
|
window: {
|
||||||
title: 'DAGGERHEART.SETTINGS.Menu.title',
|
title: 'DAGGERHEART.SETTINGS.Menu.title',
|
||||||
|
|
@ -70,6 +70,14 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_attachPartListeners(partId, htmlElement, options) {
|
||||||
|
super._attachPartListeners(partId, htmlElement, options);
|
||||||
|
|
||||||
|
htmlElement
|
||||||
|
.querySelector('.default-animations-input')
|
||||||
|
?.addEventListener('change', this.toggleSFXOverride.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
_configureRenderParts(options) {
|
_configureRenderParts(options) {
|
||||||
const parts = super._configureRenderParts(options);
|
const parts = super._configureRenderParts(options);
|
||||||
|
|
@ -83,15 +91,20 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
async _prepareContext(options) {
|
async _prepareContext(options) {
|
||||||
const context = await super._prepareContext(options);
|
const context = await super._prepareContext(options);
|
||||||
if (options.isFirstRender)
|
if (options.isFirstRender) {
|
||||||
this.setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance);
|
this.setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance);
|
||||||
|
this.globalOverrides = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.GlobalOverrides);
|
||||||
|
}
|
||||||
|
|
||||||
context.setting = this.setting;
|
context.setting = this.setting;
|
||||||
|
context.globalOverrides = this.globalOverrides;
|
||||||
context.fields = this.setting.schema.fields;
|
context.fields = this.setting.schema.fields;
|
||||||
|
|
||||||
context.tabs = this._prepareTabs('general');
|
context.tabs = this._prepareTabs('general');
|
||||||
context.dsnTabs = this._prepareTabs('diceSoNice');
|
context.dsnTabs = this._prepareTabs('diceSoNice');
|
||||||
|
|
||||||
|
context.isGM = game.user.isGM;
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,6 +133,9 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
async prepareDiceSoNiceContext(context) {
|
async prepareDiceSoNiceContext(context) {
|
||||||
|
context.animationEvents = CONFIG.DH.GENERAL.daggerheartDiceAnimationEvents;
|
||||||
|
context.previewAnimation = this.previewAnimation;
|
||||||
|
|
||||||
context.diceSoNiceTextures = Object.entries(game.dice3d.exports.TEXTURELIST).reduce(
|
context.diceSoNiceTextures = Object.entries(game.dice3d.exports.TEXTURELIST).reduce(
|
||||||
(acc, [k, v]) => ({
|
(acc, [k, v]) => ({
|
||||||
...acc,
|
...acc,
|
||||||
|
|
@ -146,6 +162,13 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
||||||
);
|
);
|
||||||
context.diceSoNiceFonts = game.dice3d.exports.Utils.prepareFontList();
|
context.diceSoNiceFonts = game.dice3d.exports.Utils.prepareFontList();
|
||||||
|
|
||||||
|
const getAnimationsOptions = key => {
|
||||||
|
const fields = context.fields.diceSoNice.fields[key].fields.sfx.fields;
|
||||||
|
return {
|
||||||
|
higher: fields.higher.fields.class.choices
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
foundry.utils.mergeObject(
|
foundry.utils.mergeObject(
|
||||||
context.dsnTabs,
|
context.dsnTabs,
|
||||||
['hope', 'fear', 'advantage', 'disadvantage'].reduce(
|
['hope', 'fear', 'advantage', 'disadvantage'].reduce(
|
||||||
|
|
@ -153,7 +176,8 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
||||||
...acc,
|
...acc,
|
||||||
[key]: {
|
[key]: {
|
||||||
values: this.setting.diceSoNice[key],
|
values: this.setting.diceSoNice[key],
|
||||||
fields: this.setting.schema.getField(`diceSoNice.${key}`).fields
|
fields: this.setting.schema.getField(`diceSoNice.${key}`).fields,
|
||||||
|
animations: ['hope', 'fear'].includes(key) ? getAnimationsOptions(key) : {}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
{}
|
{}
|
||||||
|
|
@ -169,13 +193,20 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
||||||
* @param {foundry.applications.ux.FormDataExtended} formData
|
* @param {foundry.applications.ux.FormDataExtended} formData
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
static async #onSubmit(event, form, formData) {
|
static async #onSubmit(_event, _form, formData) {
|
||||||
const data = this.setting.schema.clean(foundry.utils.expandObject(formData.object));
|
const data = this.setting.schema.clean(foundry.utils.expandObject(formData.object));
|
||||||
|
|
||||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance, data);
|
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
async toggleSFXOverride(event) {
|
||||||
|
await this.globalOverrides.diceSoNiceSFXUpdate(this.setting, event.target.checked);
|
||||||
|
this.globalOverrides = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.GlobalOverrides);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit the configuration form.
|
* Submit the configuration form.
|
||||||
* @this {DHAppearanceSettings}
|
* @this {DHAppearanceSettings}
|
||||||
|
|
@ -183,13 +214,25 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
||||||
*/
|
*/
|
||||||
static async #onPreview(_, target) {
|
static async #onPreview(_, target) {
|
||||||
const formData = new foundry.applications.ux.FormDataExtended(target.closest('form'));
|
const formData = new foundry.applications.ux.FormDataExtended(target.closest('form'));
|
||||||
const { diceSoNice } = foundry.utils.expandObject(formData.object);
|
const { diceSoNice, ...rest } = foundry.utils.expandObject(formData.object);
|
||||||
const { key } = target.dataset;
|
const { key } = target.dataset;
|
||||||
const faces = ['advantage', 'disadvantage'].includes(key) ? 'd6' : 'd12';
|
const faces = ['advantage', 'disadvantage'].includes(key) ? 'd6' : 'd12';
|
||||||
const preset = await getDiceSoNicePreset(diceSoNice[key], faces);
|
const preset = await getDiceSoNicePreset(diceSoNice[key], faces);
|
||||||
const diceSoNiceRoll = await new foundry.dice.Roll(`1${faces}`).evaluate();
|
const diceSoNiceRoll = await new foundry.dice.Roll(`1${faces}`).evaluate();
|
||||||
diceSoNiceRoll.dice[0].options.appearance = preset.appearance;
|
diceSoNiceRoll.dice[0].options.appearance = preset.appearance;
|
||||||
diceSoNiceRoll.dice[0].options.modelFile = preset.modelFile;
|
diceSoNiceRoll.dice[0].options.modelFile = preset.modelFile;
|
||||||
|
|
||||||
|
const previewAnimation = rest[`${key}PreviewAnimation`];
|
||||||
|
const events = CONFIG.DH.GENERAL.daggerheartDiceAnimationEvents;
|
||||||
|
if (previewAnimation) {
|
||||||
|
if (previewAnimation === events.critical.id && diceSoNice.sfx.critical.class) {
|
||||||
|
diceSoNiceRoll.dice[0].options.sfx = { specialEffect: diceSoNice.sfx.critical.class };
|
||||||
|
}
|
||||||
|
if (previewAnimation === events.higher.id && diceSoNice[key].sfx.higher) {
|
||||||
|
diceSoNiceRoll.dice[0].options.sfx = { specialEffect: diceSoNice[key].sfx.higher.class };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await game.dice3d.showForRoll(diceSoNiceRoll, game.user, false);
|
await game.dice3d.showForRoll(diceSoNiceRoll, game.user, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@ export default class DhAutomationSettings extends HandlebarsApplicationMixin(App
|
||||||
};
|
};
|
||||||
|
|
||||||
static PARTS = {
|
static PARTS = {
|
||||||
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
|
|
||||||
header: { template: 'systems/daggerheart/templates/settings/automation-settings/header.hbs' },
|
header: { template: 'systems/daggerheart/templates/settings/automation-settings/header.hbs' },
|
||||||
|
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
|
||||||
general: { template: 'systems/daggerheart/templates/settings/automation-settings/general.hbs' },
|
general: { template: 'systems/daggerheart/templates/settings/automation-settings/general.hbs' },
|
||||||
rules: { template: 'systems/daggerheart/templates/settings/automation-settings/deathMoves.hbs' },
|
rules: { template: 'systems/daggerheart/templates/settings/automation-settings/deathMoves.hbs' },
|
||||||
roll: { template: 'systems/daggerheart/templates/settings/automation-settings/roll.hbs' },
|
roll: { template: 'systems/daggerheart/templates/settings/automation-settings/roll.hbs' },
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { DhHomebrew } from '../../data/settings/_module.mjs';
|
import { DhHomebrew } from '../../data/settings/_module.mjs';
|
||||||
|
import { Resource } from '../../data/settings/Homebrew.mjs';
|
||||||
import { slugify } from '../../helpers/utils.mjs';
|
import { slugify } from '../../helpers/utils.mjs';
|
||||||
|
|
||||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
@ -44,6 +45,9 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
||||||
addAdversaryType: this.addAdversaryType,
|
addAdversaryType: this.addAdversaryType,
|
||||||
deleteAdversaryType: this.deleteAdversaryType,
|
deleteAdversaryType: this.deleteAdversaryType,
|
||||||
selectAdversaryType: this.selectAdversaryType,
|
selectAdversaryType: this.selectAdversaryType,
|
||||||
|
addResource: this.addResource,
|
||||||
|
removeResource: this.removeResource,
|
||||||
|
resetResourceImage: this.resetResourceImage,
|
||||||
save: this.save,
|
save: this.save,
|
||||||
resetTokenSizes: this.resetTokenSizes,
|
resetTokenSizes: this.resetTokenSizes,
|
||||||
reset: this.reset
|
reset: this.reset
|
||||||
|
|
@ -56,6 +60,10 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
||||||
settings: { template: 'systems/daggerheart/templates/settings/homebrew-settings/settings.hbs' },
|
settings: { template: 'systems/daggerheart/templates/settings/homebrew-settings/settings.hbs' },
|
||||||
domains: { template: 'systems/daggerheart/templates/settings/homebrew-settings/domains.hbs' },
|
domains: { template: 'systems/daggerheart/templates/settings/homebrew-settings/domains.hbs' },
|
||||||
types: { template: 'systems/daggerheart/templates/settings/homebrew-settings/types.hbs' },
|
types: { template: 'systems/daggerheart/templates/settings/homebrew-settings/types.hbs' },
|
||||||
|
resources: {
|
||||||
|
template: 'systems/daggerheart/templates/settings/homebrew-settings/resources.hbs',
|
||||||
|
scrollable: ['.resource-types-container']
|
||||||
|
},
|
||||||
itemTypes: { template: 'systems/daggerheart/templates/settings/homebrew-settings/itemFeatures.hbs' },
|
itemTypes: { template: 'systems/daggerheart/templates/settings/homebrew-settings/itemFeatures.hbs' },
|
||||||
downtime: { template: 'systems/daggerheart/templates/settings/homebrew-settings/downtime.hbs' },
|
downtime: { template: 'systems/daggerheart/templates/settings/homebrew-settings/downtime.hbs' },
|
||||||
footer: { template: 'systems/daggerheart/templates/settings/homebrew-settings/footer.hbs' }
|
footer: { template: 'systems/daggerheart/templates/settings/homebrew-settings/footer.hbs' }
|
||||||
|
|
@ -64,7 +72,14 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
static TABS = {
|
static TABS = {
|
||||||
main: {
|
main: {
|
||||||
tabs: [{ id: 'settings' }, { id: 'domains' }, { id: 'types' }, { id: 'itemFeatures' }, { id: 'downtime' }],
|
tabs: [
|
||||||
|
{ id: 'settings' },
|
||||||
|
{ id: 'domains' },
|
||||||
|
{ id: 'types' },
|
||||||
|
{ id: 'resources' },
|
||||||
|
{ id: 'itemFeatures' },
|
||||||
|
{ id: 'downtime' }
|
||||||
|
],
|
||||||
initial: 'settings',
|
initial: 'settings',
|
||||||
labelPrefix: 'DAGGERHEART.GENERAL.Tabs'
|
labelPrefix: 'DAGGERHEART.GENERAL.Tabs'
|
||||||
}
|
}
|
||||||
|
|
@ -77,9 +92,17 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_attachPartListeners(partId, htmlElement, options) {
|
||||||
|
super._attachPartListeners(partId, htmlElement, options);
|
||||||
|
|
||||||
|
for (const element of htmlElement.querySelectorAll('.path-field input'))
|
||||||
|
element.addEventListener('change', this.toggleResourceIsIcon.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
async _prepareContext(_options) {
|
async _prepareContext(_options) {
|
||||||
const context = await super._prepareContext(_options);
|
const context = await super._prepareContext(_options);
|
||||||
context.settingFields = this.settings;
|
context.settingFields = this.settings;
|
||||||
|
context.schemaFields = context.settingFields.schema.fields;
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
@ -103,6 +126,8 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
||||||
? { id: this.selected.adversaryType, ...this.settings.adversaryTypes[this.selected.adversaryType] }
|
? { id: this.selected.adversaryType, ...this.settings.adversaryTypes[this.selected.adversaryType] }
|
||||||
: null;
|
: null;
|
||||||
break;
|
break;
|
||||||
|
case 'resources':
|
||||||
|
break;
|
||||||
case 'downtime':
|
case 'downtime':
|
||||||
context.restOptions = {
|
context.restOptions = {
|
||||||
shortRest: CONFIG.DH.GENERAL.defaultRestOptions.shortRest(),
|
shortRest: CONFIG.DH.GENERAL.defaultRestOptions.shortRest(),
|
||||||
|
|
@ -124,6 +149,33 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async toggleResourceIsIcon(event) {
|
||||||
|
const element = event.target.closest('.resource-icon-container');
|
||||||
|
const { actorType, resourceKey, imageKey } = element.dataset;
|
||||||
|
|
||||||
|
const current = this.settings.resources[actorType].resources[resourceKey].images[imageKey];
|
||||||
|
await this.settings.updateSource({
|
||||||
|
[`resources.${actorType}.resources.${resourceKey}.images.${imageKey}`]: {
|
||||||
|
isIcon: !current.isIcon,
|
||||||
|
value: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async resetResourceImage(_event, button) {
|
||||||
|
const element = button.closest('.resource-icon-container');
|
||||||
|
const { actorType, resourceKey, imageKey } = element.dataset;
|
||||||
|
|
||||||
|
await this.settings.updateSource({
|
||||||
|
[`resources.${actorType}.resources.${resourceKey}.images.${imageKey}`]:
|
||||||
|
Resource.getDefaultImageData(imageKey)
|
||||||
|
});
|
||||||
|
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
static async changeCurrencyIcon(_, target) {
|
static async changeCurrencyIcon(_, target) {
|
||||||
const type = target.dataset.currency;
|
const type = target.dataset.currency;
|
||||||
const currentIcon = this.settings.currency[type].icon;
|
const currentIcon = this.settings.currency[type].icon;
|
||||||
|
|
@ -466,6 +518,58 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async addResource(_, target) {
|
||||||
|
const { actorType } = target.dataset;
|
||||||
|
const content = new foundry.data.fields.StringField({
|
||||||
|
label: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.resources.resourceIdentifier'),
|
||||||
|
required: true
|
||||||
|
}).toFormGroup({}, { name: 'identifier', localize: true }).outerHTML;
|
||||||
|
|
||||||
|
async function callback(_, button) {
|
||||||
|
const identifier = button.form.elements.identifier.value;
|
||||||
|
if (!identifier) return;
|
||||||
|
|
||||||
|
const sluggedIdentifier = slugify(identifier);
|
||||||
|
|
||||||
|
await this.settings.updateSource({
|
||||||
|
[`resources.${actorType}.resources.${sluggedIdentifier}`]: Resource.getDefaultResourceData(identifier)
|
||||||
|
});
|
||||||
|
|
||||||
|
game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, this.settings.toObject());
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
await foundry.applications.api.DialogV2.prompt({
|
||||||
|
content: content,
|
||||||
|
rejectClose: false,
|
||||||
|
modal: true,
|
||||||
|
ok: { callback: callback.bind(this) },
|
||||||
|
window: {
|
||||||
|
title: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.resources.setResourceIdentifier')
|
||||||
|
},
|
||||||
|
position: { width: 400 }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static async removeResource(_, target) {
|
||||||
|
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||||
|
window: {
|
||||||
|
title: game.i18n.localize(`DAGGERHEART.SETTINGS.Homebrew.deleteResourceTitle`)
|
||||||
|
},
|
||||||
|
content: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.deleteResourceText')
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!confirmed) return;
|
||||||
|
|
||||||
|
const { actorType, resourceKey } = target.dataset;
|
||||||
|
await this.settings.updateSource({
|
||||||
|
[`resources.${actorType}.resources.${resourceKey}`]: _del
|
||||||
|
});
|
||||||
|
|
||||||
|
game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, this.settings.toObject());
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
static async save() {
|
static async save() {
|
||||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, this.settings.toObject());
|
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, this.settings.toObject());
|
||||||
this.close();
|
this.close();
|
||||||
|
|
|
||||||
62
module/applications/settings/metagamingSettings.mjs
Normal file
62
module/applications/settings/metagamingSettings.mjs
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
import { DhMetagaming } from '../../data/settings/_module.mjs';
|
||||||
|
|
||||||
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
||||||
|
export default class DhMetagamingSettings extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
|
constructor() {
|
||||||
|
super({});
|
||||||
|
|
||||||
|
this.settings = new DhMetagaming(
|
||||||
|
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Metagaming).toObject()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get title() {
|
||||||
|
return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.title');
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
tag: 'form',
|
||||||
|
id: 'daggerheart-metagaming-settings',
|
||||||
|
classes: ['daggerheart', 'dh-style', 'dialog', 'setting'],
|
||||||
|
position: { width: '600', height: 'auto' },
|
||||||
|
window: {
|
||||||
|
icon: 'fa-solid fa-eye-low-vision'
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
reset: this.reset,
|
||||||
|
save: this.save
|
||||||
|
},
|
||||||
|
form: { handler: this.updateData, submitOnChange: true }
|
||||||
|
};
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
header: { template: 'systems/daggerheart/templates/settings/metagaming-settings/header.hbs' },
|
||||||
|
general: { template: 'systems/daggerheart/templates/settings/metagaming-settings/general.hbs' },
|
||||||
|
footer: { template: 'systems/daggerheart/templates/settings/metagaming-settings/footer.hbs' }
|
||||||
|
};
|
||||||
|
|
||||||
|
async _prepareContext(_options) {
|
||||||
|
const context = await super._prepareContext(_options);
|
||||||
|
context.settingFields = this.settings;
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async updateData(_event, _element, formData) {
|
||||||
|
const updatedSettings = foundry.utils.expandObject(formData.object);
|
||||||
|
|
||||||
|
await this.settings.updateSource(updatedSettings);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async reset() {
|
||||||
|
this.settings = new DhMetagaming();
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async save() {
|
||||||
|
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Metagaming, this.settings.toObject());
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { getUnusedDamageTypes } from '../../helpers/utils.mjs';
|
||||||
import DaggerheartSheet from '../sheets/daggerheart-sheet.mjs';
|
import DaggerheartSheet from '../sheets/daggerheart-sheet.mjs';
|
||||||
|
|
||||||
const { ApplicationV2 } = foundry.applications.api;
|
const { ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
@ -28,6 +29,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
removeEffect: this.removeEffect,
|
removeEffect: this.removeEffect,
|
||||||
addElement: this.addElement,
|
addElement: this.addElement,
|
||||||
removeElement: this.removeElement,
|
removeElement: this.removeElement,
|
||||||
|
removeTransformActor: this.removeTransformActor,
|
||||||
editEffect: this.editEffect,
|
editEffect: this.editEffect,
|
||||||
addDamage: this.addDamage,
|
addDamage: this.addDamage,
|
||||||
removeDamage: this.removeDamage,
|
removeDamage: this.removeDamage,
|
||||||
|
|
@ -41,7 +43,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
submitOnChange: true,
|
submitOnChange: true,
|
||||||
closeOnSubmit: false
|
closeOnSubmit: false
|
||||||
},
|
},
|
||||||
dragDrop: [{ dragSelector: null, dropSelector: '#summon-drop-zone', handlers: ['_onDrop'] }]
|
dragDrop: [{ dragSelector: null, dropSelector: '[data-is-drop-zone]', handlers: ['_onDrop'] }]
|
||||||
};
|
};
|
||||||
|
|
||||||
static PARTS = {
|
static PARTS = {
|
||||||
|
|
@ -103,7 +105,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static CLEAN_ARRAYS = ['damage.parts', 'cost', 'effects', 'summon'];
|
static CLEAN_ARRAYS = ['cost', 'effects', 'summon'];
|
||||||
|
|
||||||
_getTabs(tabs) {
|
_getTabs(tabs) {
|
||||||
for (const v of Object.values(tabs)) {
|
for (const v of Object.values(tabs)) {
|
||||||
|
|
@ -120,6 +122,10 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
htmlElement.querySelectorAll('.summon-count-wrapper input').forEach(element => {
|
htmlElement.querySelectorAll('.summon-count-wrapper input').forEach(element => {
|
||||||
element.addEventListener('change', this.updateSummonCount.bind(this));
|
element.addEventListener('change', this.updateSummonCount.bind(this));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
htmlElement.querySelectorAll('.transform-resource input').forEach(element => {
|
||||||
|
element.addEventListener('change', this.updateTransformResource.bind(this));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async _prepareContext(_options) {
|
async _prepareContext(_options) {
|
||||||
|
|
@ -133,6 +139,18 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
context.summons.push({ actor, count: summon.count });
|
context.summons.push({ actor, count: summon.count });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context.source.transform) {
|
||||||
|
const actor = await foundry.utils.fromUuid(context.source.transform.actorUUID);
|
||||||
|
context.transform = {
|
||||||
|
...context.source.transform,
|
||||||
|
actor:
|
||||||
|
actor ??
|
||||||
|
(context.source.transform.actorUUID && !actor
|
||||||
|
? { error: game.i18n.localize('DAGGERHEART.ACTIONS.Settings.transform.actorIsMissing') }
|
||||||
|
: null)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
context.openSection = this.openSection;
|
context.openSection = this.openSection;
|
||||||
context.tabs = this._getTabs(this.constructor.TABS);
|
context.tabs = this._getTabs(this.constructor.TABS);
|
||||||
context.config = CONFIG.DH;
|
context.config = CONFIG.DH;
|
||||||
|
|
@ -155,6 +173,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
revealed: this.openTrigger === index
|
revealed: this.openTrigger === index
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
context.allDamageTypesUsed = !getUnusedDamageTypes(this.action.damage.parts).length;
|
||||||
|
|
||||||
const settingsTiers = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers;
|
const settingsTiers = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers;
|
||||||
context.tierOptions = [
|
context.tierOptions = [
|
||||||
|
|
@ -266,20 +285,69 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
if (doc) return doc.sheet.render({ force: true });
|
if (doc) return doc.sheet.render({ force: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async removeTransformActor() {
|
||||||
|
const data = this.action.toObject();
|
||||||
|
data.transform.actorUUID = null;
|
||||||
|
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||||
|
}
|
||||||
|
|
||||||
static addDamage(_event) {
|
static addDamage(_event) {
|
||||||
if (!this.action.damage.parts) return;
|
if (!this.action.damage.parts) return;
|
||||||
const data = this.action.toObject(),
|
|
||||||
part = {};
|
const choices = getUnusedDamageTypes(this.action.damage.parts);
|
||||||
|
const content = new foundry.data.fields.StringField({
|
||||||
|
label: game.i18n.localize('Damage Type'),
|
||||||
|
choices,
|
||||||
|
required: true
|
||||||
|
}).toFormGroup(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
name: 'type',
|
||||||
|
localize: true,
|
||||||
|
nameAttr: 'value',
|
||||||
|
labelAttr: 'label'
|
||||||
|
}
|
||||||
|
).outerHTML;
|
||||||
|
|
||||||
|
const callback = (_, button) => {
|
||||||
|
const data = this.action.toObject();
|
||||||
|
const type = choices[button.form.elements.type.value].value;
|
||||||
|
const part = { applyTo: type };
|
||||||
if (this.action.actor?.isNPC) part.value = { multiplier: 'flat' };
|
if (this.action.actor?.isNPC) part.value = { multiplier: 'flat' };
|
||||||
data.damage.parts.push(part);
|
data.damage.parts[type] = part;
|
||||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||||
|
};
|
||||||
|
|
||||||
|
const typeDialog = new foundry.applications.api.DialogV2({
|
||||||
|
buttons: [
|
||||||
|
foundry.utils.mergeObject(
|
||||||
|
{
|
||||||
|
action: 'ok',
|
||||||
|
label: 'Confirm',
|
||||||
|
icon: 'fas fa-check',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{ callback: callback }
|
||||||
|
)
|
||||||
|
],
|
||||||
|
content: content,
|
||||||
|
rejectClose: false,
|
||||||
|
modal: false,
|
||||||
|
window: {
|
||||||
|
title: game.i18n.localize('Add Damage')
|
||||||
|
},
|
||||||
|
position: { width: 300 }
|
||||||
|
});
|
||||||
|
|
||||||
|
typeDialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static removeDamage(_event, button) {
|
static removeDamage(_event, button) {
|
||||||
if (!this.action.damage.parts) return;
|
if (!this.action.damage.parts) return;
|
||||||
const data = this.action.toObject(),
|
const data = this.action.toObject();
|
||||||
index = button.dataset.index;
|
const key = button.dataset.key;
|
||||||
data.damage.parts.splice(index, 1);
|
delete data.damage.parts[key];
|
||||||
|
data.damage.parts[`${key}`] = _del;
|
||||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -346,6 +414,14 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateTransformResource(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
const data = this.action.toObject();
|
||||||
|
data.transform.resourceRefresh[event.target.dataset.resource] = event.target.checked;
|
||||||
|
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||||
|
}
|
||||||
|
|
||||||
/** Specific implementation in extending classes **/
|
/** Specific implementation in extending classes **/
|
||||||
static async addEffect(_event) {}
|
static async addEffect(_event) {}
|
||||||
static removeEffect(_event, _button) {}
|
static removeEffect(_event, _button) {}
|
||||||
|
|
@ -364,6 +440,18 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dropZone = event.target.closest('[data-is-drop-zone]');
|
||||||
|
if (!dropZone) return;
|
||||||
|
|
||||||
|
switch (dropZone.id) {
|
||||||
|
case 'summon-drop-zone':
|
||||||
|
return this.onSummonDrop(data);
|
||||||
|
case 'transform-drop-zone':
|
||||||
|
return this.onTransformDrop(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async onSummonDrop(data) {
|
||||||
const actionData = this.action.toObject();
|
const actionData = this.action.toObject();
|
||||||
let countvalue = 1;
|
let countvalue = 1;
|
||||||
for (const entry of actionData.summon) {
|
for (const entry of actionData.summon) {
|
||||||
|
|
@ -380,4 +468,10 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
actionData.summon.push({ actorUUID: data.uuid, count: countvalue });
|
actionData.summon.push({ actorUUID: data.uuid, count: countvalue });
|
||||||
await this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(actionData) });
|
await this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(actionData) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onTransformDrop(data) {
|
||||||
|
const actionData = this.action.toObject();
|
||||||
|
actionData.transform.actorUUID = data.uuid;
|
||||||
|
await this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(actionData) });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
handleResourceDice: CharacterSheet.#handleResourceDice,
|
handleResourceDice: CharacterSheet.#handleResourceDice,
|
||||||
advanceResourceDie: CharacterSheet.#advanceResourceDie,
|
advanceResourceDie: CharacterSheet.#advanceResourceDie,
|
||||||
cancelBeastform: CharacterSheet.#cancelBeastform,
|
cancelBeastform: CharacterSheet.#cancelBeastform,
|
||||||
|
toggleResourceManagement: CharacterSheet.#toggleResourceManagement,
|
||||||
useDowntime: this.useDowntime,
|
useDowntime: this.useDowntime,
|
||||||
viewParty: CharacterSheet.#viewParty,
|
viewParty: CharacterSheet.#viewParty,
|
||||||
toggleArmorMangement: CharacterSheet.#toggleArmorManagement
|
toggleArmorMangement: CharacterSheet.#toggleArmorManagement
|
||||||
|
|
@ -227,6 +228,9 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
async _preparePartContext(partId, context, options) {
|
async _preparePartContext(partId, context, options) {
|
||||||
context = await super._preparePartContext(partId, context, options);
|
context = await super._preparePartContext(partId, context, options);
|
||||||
switch (partId) {
|
switch (partId) {
|
||||||
|
case 'header':
|
||||||
|
await this._prepareHeaderContext(context, options);
|
||||||
|
break;
|
||||||
case 'loadout':
|
case 'loadout':
|
||||||
await this._prepareLoadoutContext(context, options);
|
await this._prepareLoadoutContext(context, options);
|
||||||
break;
|
break;
|
||||||
|
|
@ -241,6 +245,12 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _prepareHeaderContext(context, _options) {
|
||||||
|
context.hasExtraResources = Object.keys(CONFIG.DH.RESOURCE.character.all).some(
|
||||||
|
key => !CONFIG.DH.RESOURCE.character.base[key]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare render context for the Loadout part.
|
* Prepare render context for the Loadout part.
|
||||||
* @param {ApplicationRenderContext} context
|
* @param {ApplicationRenderContext} context
|
||||||
|
|
@ -1057,6 +1067,77 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
await effect.update({ 'system.changes': newChanges });
|
await effect.update({ 'system.changes': newChanges });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async #toggleResourceManagement(event, button) {
|
||||||
|
event.stopPropagation();
|
||||||
|
const existingTooltip = document.body.querySelector('.locked-tooltip .resource-management-container');
|
||||||
|
if (existingTooltip) {
|
||||||
|
game.tooltip.dismissLockedTooltips();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const extraResources = Object.values(CONFIG.DH.RESOURCE.character.all).reduce((acc, resource) => {
|
||||||
|
if (CONFIG.DH.RESOURCE.character.base[resource.id]) return acc;
|
||||||
|
|
||||||
|
const resourceData = this.document.system.resources[resource.id];
|
||||||
|
acc[resource.id] = {
|
||||||
|
id: resource.id,
|
||||||
|
label: game.i18n.localize(resource.label),
|
||||||
|
value: resourceData.value,
|
||||||
|
max: resourceData.max,
|
||||||
|
fullIcon: resource.images?.full ?? { value: 'fa-solid fa-circle', isIcon: true },
|
||||||
|
emptyIcon: resource.images?.empty ?? { value: 'fa-regular fa-circle', isIcon: true }
|
||||||
|
};
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const html = document.createElement('div');
|
||||||
|
html.innerHTML = await foundry.applications.handlebars.renderTemplate(
|
||||||
|
`systems/daggerheart/templates/ui/tooltip/resourceManagement.hbs`,
|
||||||
|
{
|
||||||
|
resources: extraResources
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const target = button.closest('.resource-section');
|
||||||
|
game.tooltip.dismissLockedTooltips();
|
||||||
|
game.tooltip.activate(target, {
|
||||||
|
html,
|
||||||
|
locked: true,
|
||||||
|
cssClass: 'bordered-tooltip',
|
||||||
|
direction: 'DOWN',
|
||||||
|
noOffset: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const resourceManager = target.querySelector('.resource-manager');
|
||||||
|
resourceManager.classList.toggle('inverted');
|
||||||
|
|
||||||
|
Hooks.once(CONFIG.DH.HOOKS.hooksConfig.lockedTooltipDismissed, () => {
|
||||||
|
resourceManager.classList.toggle('inverted');
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const element of html.querySelectorAll('.resource-value'))
|
||||||
|
element.addEventListener('click', this.onUpdateResource.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
async onUpdateResource(event) {
|
||||||
|
const target = event.target.closest('.resource-value');
|
||||||
|
const { resource, value: textValue } = target.dataset;
|
||||||
|
|
||||||
|
const inputValue = Number.parseInt(textValue);
|
||||||
|
const decreasing = inputValue <= this.document.system.resources[resource].value;
|
||||||
|
const value = decreasing ? inputValue - 1 : inputValue;
|
||||||
|
await this.document.update({ [`system.resources.${resource}.value`]: value }, { render: false });
|
||||||
|
|
||||||
|
/* Update resource symbols */
|
||||||
|
const section = target.closest('.resource-section');
|
||||||
|
for (const element of section.querySelectorAll('.resource-value')) {
|
||||||
|
const showFull = Number.parseInt(element.dataset.value) <= value;
|
||||||
|
element.querySelector('.full').classList.toggle('hidden', !showFull);
|
||||||
|
element.querySelector('.empty').classList.toggle('hidden', showFull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the downtime application.
|
* Open the downtime application.
|
||||||
* @type {ApplicationClickAction}
|
* @type {ApplicationClickAction}
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,32 @@ export default class DHBaseActorSettings extends DHApplicationMixin(DocumentShee
|
||||||
const context = await super._prepareContext(options);
|
const context = await super._prepareContext(options);
|
||||||
context.isNPC = this.actor.isNPC;
|
context.isNPC = this.actor.isNPC;
|
||||||
|
|
||||||
if (context.systemFields.attack)
|
if (context.systemFields.attack) {
|
||||||
context.systemFields.attack.fields = this.actor.system.attack.schema.fields;
|
context.systemFields.attack.fields = this.actor.system.attack.schema.fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create fake fields for actor configurable max resource value.
|
||||||
|
const resourceConfig = CONFIG.DH.RESOURCE[this.actor.type]?.all;
|
||||||
|
if (resourceConfig) {
|
||||||
|
const relevant = ['hitPoints', 'stress'].filter(r => r in resourceConfig);
|
||||||
|
context.resources = relevant.map(key => {
|
||||||
|
const data = this.actor._source.system.resources[key];
|
||||||
|
const config = resourceConfig[key];
|
||||||
|
return {
|
||||||
|
label: config.label,
|
||||||
|
name: `system.resources.${key}.max`,
|
||||||
|
value: data.max ?? config.max,
|
||||||
|
tooltip: key === 'hitPoints' ? game.i18n.localize('DAGGERHEART.UI.Tooltip.maxHPClassBound') : null,
|
||||||
|
field: new foundry.data.fields.NumberField({
|
||||||
|
initial: config.max,
|
||||||
|
integer: true,
|
||||||
|
label: game.i18n.format('DAGGERHEART.GENERAL.maxWithThing', {
|
||||||
|
thing: game.i18n.localize(config.label)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,15 @@ export default function DHApplicationMixin(Base) {
|
||||||
class DHSheetV2 extends HandlebarsApplicationMixin(Base) {
|
class DHSheetV2 extends HandlebarsApplicationMixin(Base) {
|
||||||
#nonHeaderAttribution = ['environment', 'ancestry', 'community', 'domainCard'];
|
#nonHeaderAttribution = ['environment', 'ancestry', 'community', 'domainCard'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DHSheetV2Configuration} [options={}]
|
||||||
|
*/
|
||||||
|
constructor(options = {}) {
|
||||||
|
super(options);
|
||||||
|
|
||||||
|
this._setupDragDrop();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default options for the sheet.
|
* The default options for the sheet.
|
||||||
* @type {DHSheetV2Configuration}
|
* @type {DHSheetV2Configuration}
|
||||||
|
|
@ -165,7 +174,9 @@ export default function DHApplicationMixin(Base) {
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
_attachPartListeners(partId, htmlElement, options) {
|
_attachPartListeners(partId, htmlElement, options) {
|
||||||
super._attachPartListeners(partId, htmlElement, options);
|
super._attachPartListeners(partId, htmlElement, options);
|
||||||
// this._dragDrop.forEach(d => d.bind(htmlElement));
|
|
||||||
|
/* Core dragDrop from ActorDocument is always only 1. Possible we could refactor our own */
|
||||||
|
if (Array.isArray(this._dragDrop)) this._dragDrop.forEach(d => d.bind(htmlElement));
|
||||||
|
|
||||||
// Handle delta inputs
|
// Handle delta inputs
|
||||||
for (const deltaInput of htmlElement.querySelectorAll('input[data-allow-delta]')) {
|
for (const deltaInput of htmlElement.querySelectorAll('input[data-allow-delta]')) {
|
||||||
|
|
@ -338,6 +349,26 @@ export default function DHApplicationMixin(Base) {
|
||||||
/* Drag and Drop */
|
/* Drag and Drop */
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates drag-drop handlers from the configured options.
|
||||||
|
* @returns {foundry.applications.ux.DragDrop[]}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_setupDragDrop() {
|
||||||
|
if (this._dragDrop) {
|
||||||
|
this._dragDrop.callbacks.dragStart = this._onDragStart;
|
||||||
|
this._dragDrop.callback.drop = this._onDrop;
|
||||||
|
} else {
|
||||||
|
this._dragDrop = this.options.dragDrop.map(d => {
|
||||||
|
d.callbacks = {
|
||||||
|
dragstart: this._onDragStart.bind(this),
|
||||||
|
drop: this._onDrop.bind(this)
|
||||||
|
};
|
||||||
|
return new foundry.applications.ux.DragDrop.implementation(d);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle dragStart event.
|
* Handle dragStart event.
|
||||||
* @param {DragEvent} event
|
* @param {DragEvent} event
|
||||||
|
|
@ -472,7 +503,10 @@ export default function DHApplicationMixin(Base) {
|
||||||
icon: 'fa-solid fa-explosion',
|
icon: 'fa-solid fa-explosion',
|
||||||
condition: target => {
|
condition: target => {
|
||||||
const doc = getDocFromElementSync(target);
|
const doc = getDocFromElementSync(target);
|
||||||
return doc?.system?.attack?.damage.parts.length || doc?.damage?.parts.length;
|
return (
|
||||||
|
!foundry.utils.isEmpty(doc?.system?.attack?.damage.parts) ||
|
||||||
|
!foundry.utils.isEmpty(doc?.damage?.parts)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
callback: async (target, event) => {
|
callback: async (target, event) => {
|
||||||
const doc = await getDocFromElement(target),
|
const doc = await getDocFromElement(target),
|
||||||
|
|
@ -664,6 +698,9 @@ export default function DHApplicationMixin(Base) {
|
||||||
case 'weapon':
|
case 'weapon':
|
||||||
presets.folder = 'equipments.folders.weapons';
|
presets.folder = 'equipments.folders.weapons';
|
||||||
break;
|
break;
|
||||||
|
case 'feature':
|
||||||
|
presets.folder = 'features';
|
||||||
|
break;
|
||||||
case 'domainCard':
|
case 'domainCard':
|
||||||
presets.folder = 'domains';
|
presets.folder = 'domains';
|
||||||
presets.filter = {
|
presets.filter = {
|
||||||
|
|
|
||||||
|
|
@ -251,6 +251,12 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
|
|
||||||
/* If any noticeable slowdown occurs, consider replacing with enriching description on clicking to expand descriptions */
|
/* If any noticeable slowdown occurs, consider replacing with enriching description on clicking to expand descriptions */
|
||||||
for (const item of this.items) {
|
for (const item of this.items) {
|
||||||
|
if (['weapon', 'armor'].includes(item.type)) {
|
||||||
|
item.system.enrichedTags = await foundry.applications.handlebars.renderTemplate(
|
||||||
|
'systems/daggerheart/templates/sheets/global/partials/item-tags.hbs',
|
||||||
|
item.system
|
||||||
|
);
|
||||||
|
}
|
||||||
item.system.enrichedDescription =
|
item.system.enrichedDescription =
|
||||||
(await item.system.getEnrichedDescription?.()) ??
|
(await item.system.getEnrichedDescription?.()) ??
|
||||||
(await foundry.applications.ux.TextEditor.implementation.enrichHTML(item.description));
|
(await foundry.applications.ux.TextEditor.implementation.enrichHTML(item.description));
|
||||||
|
|
|
||||||
|
|
@ -52,46 +52,6 @@
|
||||||
* @extends {foundry.applications.ux.ContextMenu}
|
* @extends {foundry.applications.ux.ContextMenu}
|
||||||
*/
|
*/
|
||||||
export default class DHContextMenu extends foundry.applications.ux.ContextMenu {
|
export default class DHContextMenu extends foundry.applications.ux.ContextMenu {
|
||||||
/**
|
|
||||||
* @param {HTMLElement|jQuery} container - The HTML element that contains the context menu targets.
|
|
||||||
* @param {string} selector - A CSS selector which activates the context menu.
|
|
||||||
* @param {ContextMenuEntry[]} menuItems - An Array of entries to display in the menu
|
|
||||||
* @param {ContextMenuOptions} [options] - Additional options to configure the context menu.
|
|
||||||
*/
|
|
||||||
constructor(container, selector, menuItems, options) {
|
|
||||||
super(container, selector, menuItems, options);
|
|
||||||
|
|
||||||
/** @deprecated since v13 until v15 */
|
|
||||||
this.#jQuery = options.jQuery;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to pass jQuery objects or HTMLElement instances to callback.
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
#jQuery;
|
|
||||||
|
|
||||||
/**@inheritdoc */
|
|
||||||
activateListeners(menu) {
|
|
||||||
menu.addEventListener('click', this.#onClickItem.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle click events on context menu items.
|
|
||||||
* @param {PointerEvent} event The click event
|
|
||||||
*/
|
|
||||||
#onClickItem(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
const element = event.target.closest('.context-item');
|
|
||||||
if (!element) return;
|
|
||||||
const item = this.menuItems.find(i => i.element === element);
|
|
||||||
item?.onClick(event, this.#jQuery ? $(this.target) : this.target);
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trigger a context menu event in response to a normal click on a additional options button.
|
* Trigger a context menu event in response to a normal click on a additional options button.
|
||||||
* @param {PointerEvent} event
|
* @param {PointerEvent} event
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,56 @@ export default class DhRegionLayer extends foundry.canvas.layers.RegionLayer {
|
||||||
const hole = ui.controls.controls[this.options.name].tools.hole?.active ?? false;
|
const hole = ui.controls.controls[this.options.name].tools.hole?.active ?? false;
|
||||||
if (game.activeTool === 'inFront') return { type: 'cone', x: 0, y: 0, radius: 0, angle: 180, hole };
|
if (game.activeTool === 'inFront') return { type: 'cone', x: 0, y: 0, radius: 0, angle: 180, hole };
|
||||||
|
|
||||||
return super._createDragShapeData(event);
|
const shape = super._createDragShapeData(event);
|
||||||
|
const token =
|
||||||
|
shape?.type === 'emanation' && shape.base?.type === 'token'
|
||||||
|
? this.#findTokenInBounds(event.interactionData.origin)
|
||||||
|
: null;
|
||||||
|
if (token) {
|
||||||
|
shape.base.width = token.width;
|
||||||
|
shape.base.height = token.height;
|
||||||
|
event.interactionData.origin = token.getCenterPoint();
|
||||||
|
}
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
async placeRegion(data, options = {}) {
|
||||||
|
const preConfirm = ({ _event, document, _create, _options }) => {
|
||||||
|
const shape = document.shapes[0];
|
||||||
|
const isEmanation = shape.type === 'emanation';
|
||||||
|
if (isEmanation) {
|
||||||
|
const token = this.#findTokenInBounds(shape.base.origin);
|
||||||
|
if (!token) return options.preConfirm?.() ?? true;
|
||||||
|
const shapeData = shape.toObject();
|
||||||
|
document.updateSource({
|
||||||
|
shapes: [
|
||||||
|
{
|
||||||
|
...shapeData,
|
||||||
|
base: {
|
||||||
|
...shapeData.base,
|
||||||
|
height: token.height,
|
||||||
|
width: token.width,
|
||||||
|
x: token.x,
|
||||||
|
y: token.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return options?.preConfirm?.() ?? true;
|
||||||
|
};
|
||||||
|
|
||||||
|
super.placeRegion(data, { ...options, preConfirm });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Searches for token at origin point, returning null if there are no tokens or multiple overlapping tokens */
|
||||||
|
#findTokenInBounds(origin) {
|
||||||
|
const { x, y } = origin;
|
||||||
|
const gridSize = canvas.grid.size;
|
||||||
|
const inBounds = canvas.scene.tokens.filter(t => {
|
||||||
|
return x.between(t.x, t.x + t.width * gridSize) && y.between(t.y, t.y + t.height * gridSize);
|
||||||
|
});
|
||||||
|
return inBounds.length === 1 ? inBounds[0] : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
export default class DhTemplateLayer extends foundry.canvas.layers.TemplateLayer {
|
|
||||||
static prepareSceneControls() {
|
|
||||||
const sc = foundry.applications.ui.SceneControls;
|
|
||||||
return {
|
|
||||||
name: 'templates',
|
|
||||||
order: 2,
|
|
||||||
title: 'CONTROLS.GroupMeasure',
|
|
||||||
icon: 'fa-solid fa-ruler-combined',
|
|
||||||
visible: game.user.can('REGION_CREATE'),
|
|
||||||
onChange: (event, active) => {
|
|
||||||
if (active) canvas.templates.activate();
|
|
||||||
},
|
|
||||||
onToolChange: () => canvas.templates.setAllRenderFlags({ refreshState: true }),
|
|
||||||
tools: {
|
|
||||||
circle: {
|
|
||||||
name: 'circle',
|
|
||||||
order: 1,
|
|
||||||
title: 'CONTROLS.MeasureCircle',
|
|
||||||
icon: 'fa-regular fa-circle',
|
|
||||||
toolclip: {
|
|
||||||
src: 'toolclips/tools/measure-circle.webm',
|
|
||||||
heading: 'CONTROLS.MeasureCircle',
|
|
||||||
items: sc.buildToolclipItems(['create', 'move', 'edit', 'hide', 'delete'])
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cone: {
|
|
||||||
name: 'cone',
|
|
||||||
order: 2,
|
|
||||||
title: 'CONTROLS.MeasureCone',
|
|
||||||
icon: 'fa-solid fa-angle-left',
|
|
||||||
toolclip: {
|
|
||||||
src: 'toolclips/tools/measure-cone.webm',
|
|
||||||
heading: 'CONTROLS.MeasureCone',
|
|
||||||
items: sc.buildToolclipItems(['create', 'move', 'edit', 'hide', 'delete', 'rotate'])
|
|
||||||
}
|
|
||||||
},
|
|
||||||
inFront: {
|
|
||||||
name: 'inFront',
|
|
||||||
order: 3,
|
|
||||||
title: 'CONTROLS.inFront',
|
|
||||||
icon: 'fa-solid fa-eye',
|
|
||||||
toolclip: {
|
|
||||||
src: 'toolclips/tools/measure-cone.webm',
|
|
||||||
heading: 'CONTROLS.inFront',
|
|
||||||
items: sc.buildToolclipItems(['create', 'move', 'edit', 'hide', 'delete', 'rotate'])
|
|
||||||
}
|
|
||||||
},
|
|
||||||
rect: {
|
|
||||||
name: 'rect',
|
|
||||||
order: 4,
|
|
||||||
title: 'CONTROLS.MeasureRect',
|
|
||||||
icon: 'fa-regular fa-square',
|
|
||||||
toolclip: {
|
|
||||||
src: 'toolclips/tools/measure-rect.webm',
|
|
||||||
heading: 'CONTROLS.MeasureRect',
|
|
||||||
items: sc.buildToolclipItems(['create', 'move', 'edit', 'hide', 'delete', 'rotate'])
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ray: {
|
|
||||||
name: 'ray',
|
|
||||||
order: 5,
|
|
||||||
title: 'CONTROLS.MeasureRay',
|
|
||||||
icon: 'fa-solid fa-up-down',
|
|
||||||
toolclip: {
|
|
||||||
src: 'toolclips/tools/measure-ray.webm',
|
|
||||||
heading: 'CONTROLS.MeasureRay',
|
|
||||||
items: sc.buildToolclipItems(['create', 'move', 'edit', 'hide', 'delete', 'rotate'])
|
|
||||||
}
|
|
||||||
},
|
|
||||||
clear: {
|
|
||||||
name: 'clear',
|
|
||||||
order: 6,
|
|
||||||
title: 'CONTROLS.MeasureClear',
|
|
||||||
icon: 'fa-solid fa-trash',
|
|
||||||
visible: game.user.isGM,
|
|
||||||
onChange: () => canvas.templates.deleteAll(),
|
|
||||||
button: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
activeTool: 'circle'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_onDragLeftStart(event) {
|
|
||||||
const interaction = event.interactionData;
|
|
||||||
|
|
||||||
// Snap the origin to the grid
|
|
||||||
if (!event.shiftKey) interaction.origin = this.getSnappedPoint(interaction.origin);
|
|
||||||
|
|
||||||
// Create a pending MeasuredTemplateDocument
|
|
||||||
const tool = game.activeTool === 'inFront' ? 'cone' : game.activeTool;
|
|
||||||
const previewData = {
|
|
||||||
user: game.user.id,
|
|
||||||
t: tool,
|
|
||||||
x: interaction.origin.x,
|
|
||||||
y: interaction.origin.y,
|
|
||||||
sort: Math.max(this.getMaxSort() + 1, 0),
|
|
||||||
distance: 1,
|
|
||||||
direction: 0,
|
|
||||||
fillColor: game.user.color || '#FF0000',
|
|
||||||
hidden: event.altKey
|
|
||||||
};
|
|
||||||
const defaults = CONFIG.MeasuredTemplate.defaults;
|
|
||||||
if (game.activeTool === 'cone') previewData.angle = defaults.angle;
|
|
||||||
else if (game.activeTool === 'inFront') previewData.angle = 180;
|
|
||||||
else if (game.activeTool === 'ray') previewData.width = defaults.width * canvas.dimensions.distance;
|
|
||||||
const cls = foundry.utils.getDocumentClass('MeasuredTemplate');
|
|
||||||
const doc = new cls(previewData, { parent: canvas.scene });
|
|
||||||
|
|
||||||
// Create a preview MeasuredTemplate object
|
|
||||||
const template = new this.constructor.placeableClass(doc);
|
|
||||||
doc._object = template;
|
|
||||||
interaction.preview = this.preview.addChild(template);
|
|
||||||
template.draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -11,3 +11,4 @@ export * as settingsConfig from './settingsConfig.mjs';
|
||||||
export * as systemConfig from './system.mjs';
|
export * as systemConfig from './system.mjs';
|
||||||
export * as itemBrowserConfig from './itemBrowserConfig.mjs';
|
export * as itemBrowserConfig from './itemBrowserConfig.mjs';
|
||||||
export * as triggerConfig from './triggerConfig.mjs';
|
export * as triggerConfig from './triggerConfig.mjs';
|
||||||
|
export * as resourceConfig from './resourceConfig.mjs';
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,12 @@ export const actionTypes = {
|
||||||
icon: 'fa-ghost',
|
icon: 'fa-ghost',
|
||||||
tooltip: 'DAGGERHEART.ACTIONS.TYPES.summon.tooltip'
|
tooltip: 'DAGGERHEART.ACTIONS.TYPES.summon.tooltip'
|
||||||
},
|
},
|
||||||
|
transform: {
|
||||||
|
id: 'transform',
|
||||||
|
name: 'DAGGERHEART.ACTIONS.TYPES.transform.name',
|
||||||
|
icon: 'fa-dragon',
|
||||||
|
tooltip: 'DAGGERHEART.ACTIONS.TYPES.transform.tooltip'
|
||||||
|
},
|
||||||
effect: {
|
effect: {
|
||||||
id: 'effect',
|
id: 'effect',
|
||||||
name: 'DAGGERHEART.ACTIONS.TYPES.effect.name',
|
name: 'DAGGERHEART.ACTIONS.TYPES.effect.name',
|
||||||
|
|
|
||||||
|
|
@ -55,24 +55,6 @@ export const abilities = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const scrollingTextResource = {
|
|
||||||
hitPoints: {
|
|
||||||
label: 'DAGGERHEART.GENERAL.HitPoints.plural',
|
|
||||||
reversed: true
|
|
||||||
},
|
|
||||||
stress: {
|
|
||||||
label: 'DAGGERHEART.GENERAL.stress',
|
|
||||||
reversed: true
|
|
||||||
},
|
|
||||||
hope: {
|
|
||||||
label: 'DAGGERHEART.GENERAL.hope'
|
|
||||||
},
|
|
||||||
armor: {
|
|
||||||
label: 'DAGGERHEART.GENERAL.armor',
|
|
||||||
reversed: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const featureProperties = {
|
export const featureProperties = {
|
||||||
agility: {
|
agility: {
|
||||||
name: 'DAGGERHEART.CONFIG.Traits.agility.name',
|
name: 'DAGGERHEART.CONFIG.Traits.agility.name',
|
||||||
|
|
|
||||||
|
|
@ -245,8 +245,8 @@ export const defaultRestOptions = {
|
||||||
type: 'friendly'
|
type: 'friendly'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
hitPoints: {
|
||||||
applyTo: healingTypes.hitPoints.id,
|
applyTo: healingTypes.hitPoints.id,
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -255,7 +255,7 @@ export const defaultRestOptions = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -279,8 +279,8 @@ export const defaultRestOptions = {
|
||||||
type: 'self'
|
type: 'self'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
stress: {
|
||||||
applyTo: healingTypes.stress.id,
|
applyTo: healingTypes.stress.id,
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -289,7 +289,7 @@ export const defaultRestOptions = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -314,8 +314,8 @@ export const defaultRestOptions = {
|
||||||
type: 'friendly'
|
type: 'friendly'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
armor: {
|
||||||
applyTo: healingTypes.armor.id,
|
applyTo: healingTypes.armor.id,
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -324,7 +324,7 @@ export const defaultRestOptions = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -348,8 +348,8 @@ export const defaultRestOptions = {
|
||||||
type: 'self'
|
type: 'self'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
hope: {
|
||||||
applyTo: healingTypes.hope.id,
|
applyTo: healingTypes.hope.id,
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -358,7 +358,7 @@ export const defaultRestOptions = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
prepareWithFriends: {
|
prepareWithFriends: {
|
||||||
|
|
@ -372,8 +372,8 @@ export const defaultRestOptions = {
|
||||||
type: 'self'
|
type: 'self'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
hope: {
|
||||||
applyTo: healingTypes.hope.id,
|
applyTo: healingTypes.hope.id,
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -382,7 +382,7 @@ export const defaultRestOptions = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -409,8 +409,8 @@ export const defaultRestOptions = {
|
||||||
type: 'friendly'
|
type: 'friendly'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
hitPoints: {
|
||||||
applyTo: healingTypes.hitPoints.id,
|
applyTo: healingTypes.hitPoints.id,
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -419,7 +419,7 @@ export const defaultRestOptions = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -443,8 +443,8 @@ export const defaultRestOptions = {
|
||||||
type: 'self'
|
type: 'self'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
stress: {
|
||||||
applyTo: healingTypes.stress.id,
|
applyTo: healingTypes.stress.id,
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -453,7 +453,7 @@ export const defaultRestOptions = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -478,8 +478,8 @@ export const defaultRestOptions = {
|
||||||
type: 'friendly'
|
type: 'friendly'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
armor: {
|
||||||
applyTo: healingTypes.armor.id,
|
applyTo: healingTypes.armor.id,
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -488,7 +488,7 @@ export const defaultRestOptions = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -512,8 +512,8 @@ export const defaultRestOptions = {
|
||||||
type: 'self'
|
type: 'self'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
hope: {
|
||||||
applyTo: healingTypes.hope.id,
|
applyTo: healingTypes.hope.id,
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -522,7 +522,7 @@ export const defaultRestOptions = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
prepareWithFriends: {
|
prepareWithFriends: {
|
||||||
|
|
@ -536,8 +536,8 @@ export const defaultRestOptions = {
|
||||||
type: 'self'
|
type: 'self'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
hope: {
|
||||||
applyTo: healingTypes.hope.id,
|
applyTo: healingTypes.hope.id,
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -546,7 +546,7 @@ export const defaultRestOptions = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -634,7 +634,95 @@ export const diceSetNumbers = {
|
||||||
flat: 'Flat'
|
flat: 'Flat'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDiceSoNicePreset = async (type, faces) => {
|
export const diceSoNiceSFXClasses = {
|
||||||
|
PlayAnimationBright: {
|
||||||
|
id: 'PlayAnimationBright',
|
||||||
|
label: 'DICESONICE.PlayAnimationBright'
|
||||||
|
},
|
||||||
|
PlayAnimationDark: {
|
||||||
|
id: 'PlayAnimationDark',
|
||||||
|
label: 'DICESONICE.PlayAnimationDark'
|
||||||
|
},
|
||||||
|
PlayAnimationOutline: {
|
||||||
|
id: 'PlayAnimationOutline',
|
||||||
|
label: 'DICESONICE.PlayAnimationOutline'
|
||||||
|
},
|
||||||
|
PlayAnimationImpact: {
|
||||||
|
id: 'PlayAnimationImpact',
|
||||||
|
label: 'DICESONICE.PlayAnimationImpact'
|
||||||
|
},
|
||||||
|
// PlayConfettiStrength1: {
|
||||||
|
// id: 'PlayConfettiStrength1',
|
||||||
|
// label: 'DICESONICE.PlayConfettiStrength1'
|
||||||
|
// },
|
||||||
|
// PlayConfettiStrength2: {
|
||||||
|
// id: 'PlayConfettiStrength2',
|
||||||
|
// label: 'DICESONICE.PlayConfettiStrength2'
|
||||||
|
// },
|
||||||
|
// PlayConfettiStrength3: {
|
||||||
|
// id: 'PlayConfettiStrength3',
|
||||||
|
// label: 'DICESONICE.PlayConfettiStrength3'
|
||||||
|
// },
|
||||||
|
PlayAnimationThormund: {
|
||||||
|
id: 'PlayAnimationThormund',
|
||||||
|
label: 'DICESONICE.PlayAnimationThormund'
|
||||||
|
},
|
||||||
|
PlayAnimationParticleSpiral: {
|
||||||
|
id: 'PlayAnimationParticleSpiral',
|
||||||
|
label: 'DICESONICE.PlayAnimationParticleSpiral'
|
||||||
|
},
|
||||||
|
PlayAnimationParticleSparkles: {
|
||||||
|
id: 'PlayAnimationParticleSparkles',
|
||||||
|
label: 'DICESONICE.PlayAnimationParticleSparkles'
|
||||||
|
},
|
||||||
|
PlayAnimationParticleVortex: {
|
||||||
|
id: 'PlayAnimationParticleVortex',
|
||||||
|
label: 'DICESONICE.PlayAnimationParticleVortex'
|
||||||
|
},
|
||||||
|
PlaySoundEpicWin: {
|
||||||
|
id: 'PlaySoundEpicWin',
|
||||||
|
label: 'DICESONICE.PlaySoundEpicWin'
|
||||||
|
},
|
||||||
|
PlaySoundEpicFail: {
|
||||||
|
id: 'PlaySoundEpicFail',
|
||||||
|
label: 'DICESONICE.PlaySoundEpicFail'
|
||||||
|
}
|
||||||
|
// "PlaySoundCustom",
|
||||||
|
// "PlayMacro"
|
||||||
|
};
|
||||||
|
|
||||||
|
export const daggerheartDiceAnimationEvents = {
|
||||||
|
critical: {
|
||||||
|
id: 'critical',
|
||||||
|
label: 'DAGGERHEART.CONFIG.DaggerheartDiceAnimationEvents.critical.name'
|
||||||
|
},
|
||||||
|
higher: {
|
||||||
|
id: 'higher',
|
||||||
|
label: 'DAGGERHEART.CONFIG.DaggerheartDiceAnimationEvents.higher.name'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDiceSoNiceSFX = sfxOptions => {
|
||||||
|
const diceSoNice = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance).diceSoNiceData;
|
||||||
|
const criticalAnimationData = diceSoNice.sfx.critical;
|
||||||
|
if (sfxOptions.critical && criticalAnimationData.class) {
|
||||||
|
return {
|
||||||
|
specialEffect: criticalAnimationData.class,
|
||||||
|
options: {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sfxOptions.higher && sfxOptions.data.higher) {
|
||||||
|
return {
|
||||||
|
specialEffect: sfxOptions.data.higher.class,
|
||||||
|
options: {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getDiceSoNicePreset = async (type, faces, sfxOptions = {}) => {
|
||||||
const system = game.dice3d.DiceFactory.systems.get(type.system).dice.get(faces);
|
const system = game.dice3d.DiceFactory.systems.get(type.system).dice.get(faces);
|
||||||
if (!system) {
|
if (!system) {
|
||||||
ui.notifications.error(
|
ui.notifications.error(
|
||||||
|
|
@ -657,16 +745,33 @@ export const getDiceSoNicePreset = async (type, faces) => {
|
||||||
appearance: {
|
appearance: {
|
||||||
...system.appearance,
|
...system.appearance,
|
||||||
...type
|
...type
|
||||||
}
|
},
|
||||||
|
sfx: getDiceSoNiceSFX(sfxOptions)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDiceSoNicePresets = async (hopeFaces, fearFaces, advantageFaces = 'd6', disadvantageFaces = 'd6') => {
|
export const getDiceSoNicePresets = async (
|
||||||
const { diceSoNice } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance);
|
result,
|
||||||
|
hopeFaces,
|
||||||
|
fearFaces,
|
||||||
|
advantageFaces = 'd6',
|
||||||
|
disadvantageFaces = 'd6'
|
||||||
|
) => {
|
||||||
|
const diceSoNice = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance).diceSoNiceData;
|
||||||
|
|
||||||
|
const { isCritical, withHope, withFear } = result;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hope: await getDiceSoNicePreset(diceSoNice.hope, hopeFaces),
|
hope: await getDiceSoNicePreset(diceSoNice.hope, hopeFaces, {
|
||||||
fear: await getDiceSoNicePreset(diceSoNice.fear, fearFaces),
|
critical: isCritical,
|
||||||
|
higher: withHope,
|
||||||
|
data: diceSoNice.hope.sfx
|
||||||
|
}),
|
||||||
|
fear: await getDiceSoNicePreset(diceSoNice.fear, fearFaces, {
|
||||||
|
critical: isCritical,
|
||||||
|
higher: withFear,
|
||||||
|
data: diceSoNice.fear.sfx
|
||||||
|
}),
|
||||||
advantage: await getDiceSoNicePreset(diceSoNice.advantage, advantageFaces),
|
advantage: await getDiceSoNicePreset(diceSoNice.advantage, advantageFaces),
|
||||||
disadvantage: await getDiceSoNicePreset(diceSoNice.disadvantage, disadvantageFaces)
|
disadvantage: await getDiceSoNicePreset(diceSoNice.disadvantage, disadvantageFaces)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
export const hooksConfig = {
|
export const hooksConfig = {
|
||||||
effectDisplayToggle: 'DHEffectDisplayToggle'
|
effectDisplayToggle: 'DHEffectDisplayToggle',
|
||||||
|
lockedTooltipDismissed: 'DHLockedTooltipDismissed'
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ export const armorFeatures = {
|
||||||
type: 'hostile'
|
type: 'hostile'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
stress: {
|
||||||
applyTo: 'stress',
|
applyTo: 'stress',
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -24,7 +24,7 @@ export const armorFeatures = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
@ -739,8 +739,8 @@ export const weaponFeatures = {
|
||||||
type: 'hostile'
|
type: 'hostile'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
stress: {
|
||||||
applyTo: 'stress',
|
applyTo: 'stress',
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -749,7 +749,7 @@ export const weaponFeatures = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -936,8 +936,8 @@ export const weaponFeatures = {
|
||||||
type: 'self'
|
type: 'self'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
hitPoints: {
|
||||||
applyTo: 'hitPoints',
|
applyTo: 'hitPoints',
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -946,7 +946,7 @@ export const weaponFeatures = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
88
module/config/resourceConfig.mjs
Normal file
88
module/config/resourceConfig.mjs
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
/**
|
||||||
|
* Full custom typing:
|
||||||
|
* id
|
||||||
|
* initial
|
||||||
|
* max
|
||||||
|
* reverse
|
||||||
|
* label
|
||||||
|
* images {
|
||||||
|
* full { value, isIcon, noColorFilter }
|
||||||
|
* empty { value, isIcon noColorFilter }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
const characterBaseResources = Object.freeze({
|
||||||
|
hitPoints: {
|
||||||
|
id: 'hitPoints',
|
||||||
|
initial: 0,
|
||||||
|
max: 0,
|
||||||
|
reverse: true,
|
||||||
|
label: 'DAGGERHEART.GENERAL.HitPoints.plural',
|
||||||
|
maxLabel: 'DAGGERHEART.ACTORS.Character.maxHPBonus'
|
||||||
|
},
|
||||||
|
stress: {
|
||||||
|
id: 'stress',
|
||||||
|
initial: 0,
|
||||||
|
max: 6,
|
||||||
|
reverse: true,
|
||||||
|
label: 'DAGGERHEART.GENERAL.stress'
|
||||||
|
},
|
||||||
|
hope: {
|
||||||
|
id: 'hope',
|
||||||
|
initial: 2,
|
||||||
|
reverse: false,
|
||||||
|
label: 'DAGGERHEART.GENERAL.hope'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const adversaryBaseResources = Object.freeze({
|
||||||
|
hitPoints: {
|
||||||
|
id: 'hitPoints',
|
||||||
|
initial: 0,
|
||||||
|
max: 0,
|
||||||
|
reverse: true,
|
||||||
|
label: 'DAGGERHEART.GENERAL.HitPoints.plural',
|
||||||
|
maxLabel: 'DAGGERHEART.ACTORS.Character.maxHPBonus'
|
||||||
|
},
|
||||||
|
stress: {
|
||||||
|
id: 'stress',
|
||||||
|
initial: 0,
|
||||||
|
max: 0,
|
||||||
|
reverse: true,
|
||||||
|
label: 'DAGGERHEART.GENERAL.stress'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const companionBaseResources = Object.freeze({
|
||||||
|
stress: {
|
||||||
|
id: 'stress',
|
||||||
|
initial: 0,
|
||||||
|
max: 0,
|
||||||
|
reverse: true,
|
||||||
|
label: 'DAGGERHEART.GENERAL.stress'
|
||||||
|
},
|
||||||
|
hope: {
|
||||||
|
id: 'hope',
|
||||||
|
initial: 0,
|
||||||
|
reverse: false,
|
||||||
|
label: 'DAGGERHEART.GENERAL.hope'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const character = {
|
||||||
|
base: characterBaseResources,
|
||||||
|
custom: {}, // module stuff goes here
|
||||||
|
all: { ...characterBaseResources }
|
||||||
|
};
|
||||||
|
|
||||||
|
export const adversary = {
|
||||||
|
base: adversaryBaseResources,
|
||||||
|
custom: {}, // module stuff goes here
|
||||||
|
all: { ...adversaryBaseResources }
|
||||||
|
};
|
||||||
|
|
||||||
|
export const companion = {
|
||||||
|
base: companionBaseResources,
|
||||||
|
custom: {}, // module stuff goes here
|
||||||
|
all: { ...companionBaseResources }
|
||||||
|
};
|
||||||
|
|
@ -3,6 +3,10 @@ export const menu = {
|
||||||
Name: 'GameSettingsAutomation',
|
Name: 'GameSettingsAutomation',
|
||||||
Icon: 'fa-solid fa-robot'
|
Icon: 'fa-solid fa-robot'
|
||||||
},
|
},
|
||||||
|
Metagaming: {
|
||||||
|
Name: 'GameSettingsMetagaming',
|
||||||
|
Icon: 'fa-solid fa-eye-low-vision'
|
||||||
|
},
|
||||||
Homebrew: {
|
Homebrew: {
|
||||||
Name: 'GameSettingsHomebrew',
|
Name: 'GameSettingsHomebrew',
|
||||||
Icon: 'fa-solid fa-flask-vial'
|
Icon: 'fa-solid fa-flask-vial'
|
||||||
|
|
@ -19,8 +23,10 @@ export const menu = {
|
||||||
|
|
||||||
export const gameSettings = {
|
export const gameSettings = {
|
||||||
Automation: 'Automation',
|
Automation: 'Automation',
|
||||||
|
Metagaming: 'Metagaming',
|
||||||
Homebrew: 'Homebrew',
|
Homebrew: 'Homebrew',
|
||||||
appearance: 'Appearance',
|
appearance: 'Appearance',
|
||||||
|
GlobalOverrides: 'GlobalOverrides',
|
||||||
variantRules: 'VariantRules',
|
variantRules: 'VariantRules',
|
||||||
Resources: {
|
Resources: {
|
||||||
Fear: 'ResourcesFear'
|
Fear: 'ResourcesFear'
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import * as GENERAL from './generalConfig.mjs';
|
||||||
import * as DOMAIN from './domainConfig.mjs';
|
import * as DOMAIN from './domainConfig.mjs';
|
||||||
import * as ENCOUNTER from './encounterConfig.mjs';
|
import * as ENCOUNTER from './encounterConfig.mjs';
|
||||||
import * as ACTOR from './actorConfig.mjs';
|
import * as ACTOR from './actorConfig.mjs';
|
||||||
|
import * as RESOURCE from './resourceConfig.mjs';
|
||||||
import * as ITEM from './itemConfig.mjs';
|
import * as ITEM from './itemConfig.mjs';
|
||||||
import * as SETTINGS from './settingsConfig.mjs';
|
import * as SETTINGS from './settingsConfig.mjs';
|
||||||
import * as EFFECTS from './effectConfig.mjs';
|
import * as EFFECTS from './effectConfig.mjs';
|
||||||
|
|
@ -19,6 +20,7 @@ export const SYSTEM = {
|
||||||
GENERAL,
|
GENERAL,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
ACTOR,
|
ACTOR,
|
||||||
|
RESOURCE,
|
||||||
ITEM,
|
ITEM,
|
||||||
SETTINGS,
|
SETTINGS,
|
||||||
EFFECTS,
|
EFFECTS,
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import EffectAction from './effectAction.mjs';
|
||||||
import HealingAction from './healingAction.mjs';
|
import HealingAction from './healingAction.mjs';
|
||||||
import MacroAction from './macroAction.mjs';
|
import MacroAction from './macroAction.mjs';
|
||||||
import SummonAction from './summonAction.mjs';
|
import SummonAction from './summonAction.mjs';
|
||||||
|
import TransformAction from './transformAction.mjs';
|
||||||
|
|
||||||
export const actionsTypes = {
|
export const actionsTypes = {
|
||||||
base: BaseAction,
|
base: BaseAction,
|
||||||
|
|
@ -17,5 +18,6 @@ export const actionsTypes = {
|
||||||
summon: SummonAction,
|
summon: SummonAction,
|
||||||
effect: EffectAction,
|
effect: EffectAction,
|
||||||
macro: MacroAction,
|
macro: MacroAction,
|
||||||
beastform: BeastformAction
|
beastform: BeastformAction,
|
||||||
|
transform: TransformAction
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -26,23 +26,23 @@ export default class DHAttackAction extends DHDamageAction {
|
||||||
return {
|
return {
|
||||||
value: {
|
value: {
|
||||||
multiplier: 'prof',
|
multiplier: 'prof',
|
||||||
dice: this.item?.system?.attack.damage.parts[0].value.dice,
|
dice: this.item?.system?.attack.damage.parts.hitPoints.value.dice,
|
||||||
bonus: this.item?.system?.attack.damage.parts[0].value.bonus ?? 0
|
bonus: this.item?.system?.attack.damage.parts.hitPoints.value.bonus ?? 0
|
||||||
},
|
},
|
||||||
type: this.item?.system?.attack.damage.parts[0].type,
|
type: this.item?.system?.attack.damage.parts.hitPoints.type,
|
||||||
base: true
|
base: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
get damageFormula() {
|
get damageFormula() {
|
||||||
const hitPointsPart = this.damage.parts.find(x => x.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id);
|
const hitPointsPart = this.damage.parts.hitPoints;
|
||||||
if (!hitPointsPart) return '0';
|
if (!hitPointsPart) return '0';
|
||||||
|
|
||||||
return hitPointsPart.value.getFormula();
|
return hitPointsPart.value.getFormula();
|
||||||
}
|
}
|
||||||
|
|
||||||
get altDamageFormula() {
|
get altDamageFormula() {
|
||||||
const hitPointsPart = this.damage.parts.find(x => x.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id);
|
const hitPointsPart = this.damage.parts.hitPoints;
|
||||||
if (!hitPointsPart) return '0';
|
if (!hitPointsPart) return '0';
|
||||||
|
|
||||||
return hitPointsPart.valueAlt.getFormula();
|
return hitPointsPart.valueAlt.getFormula();
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
async executeWorkflow(config) {
|
async executeWorkflow(config) {
|
||||||
for (const [key, part] of this.workflow) {
|
for (const [key, part] of this.workflow) {
|
||||||
if (Hooks.call(`${CONFIG.DH.id}.pre${key.capitalize()}Action`, this, config) === false) return;
|
if (Hooks.call(`${CONFIG.DH.id}.pre${key.capitalize()}Action`, this, config) === false) return;
|
||||||
if ((await part.execute(config)) === false) return;
|
if ((await part.execute(config)) === false) return false;
|
||||||
if (Hooks.call(`${CONFIG.DH.id}.post${key.capitalize()}Action`, this, config) === false) return;
|
if (Hooks.call(`${CONFIG.DH.id}.post${key.capitalize()}Action`, this, config) === false) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -224,7 +224,9 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the Action Worflow in order based of schema fields
|
// Execute the Action Worflow in order based of schema fields
|
||||||
await this.executeWorkflow(config);
|
const result = await this.executeWorkflow(config);
|
||||||
|
if (result === false) return;
|
||||||
|
|
||||||
await config.resourceUpdates.updateResources();
|
await config.resourceUpdates.updateResources();
|
||||||
|
|
||||||
if (Hooks.call(`${CONFIG.DH.id}.postUseAction`, this, config) === false) return;
|
if (Hooks.call(`${CONFIG.DH.id}.postUseAction`, this, config) === false) return;
|
||||||
|
|
@ -354,11 +356,11 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasDamage() {
|
get hasDamage() {
|
||||||
return this.damage?.parts?.length && this.type !== 'healing';
|
return !foundry.utils.isEmpty(this.damage?.parts) && this.type !== 'healing';
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasHealing() {
|
get hasHealing() {
|
||||||
return this.damage?.parts?.length && this.type === 'healing';
|
return !foundry.utils.isEmpty(this.damage?.parts) && this.type === 'healing';
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasSave() {
|
get hasSave() {
|
||||||
|
|
@ -378,6 +380,15 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
|
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static migrateData(source) {
|
||||||
|
if (source.damage?.parts && Array.isArray(source.damage.parts)) {
|
||||||
|
source.damage.parts = source.damage.parts.reduce((acc, part) => {
|
||||||
|
acc[part.applyTo] = part;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ResourceUpdateMap extends Map {
|
export class ResourceUpdateMap extends Map {
|
||||||
|
|
|
||||||
5
module/data/action/transformAction.mjs
Normal file
5
module/data/action/transformAction.mjs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
import DHBaseAction from './baseAction.mjs';
|
||||||
|
|
||||||
|
export default class DHTransformAction extends DHBaseAction {
|
||||||
|
static extraSchemas = [...super.extraSchemas, 'transform'];
|
||||||
|
}
|
||||||
|
|
@ -227,9 +227,9 @@ export default class ArmorEffect extends foundry.data.ActiveEffectTypeDataModel
|
||||||
changes.system.changes[0].value !== this.armorChange.value &&
|
changes.system.changes[0].value !== this.armorChange.value &&
|
||||||
this.parent.actor?.type === 'character'
|
this.parent.actor?.type === 'character'
|
||||||
) {
|
) {
|
||||||
const increased = changes.system.changes[0].value > this.armorChange.value;
|
options.scrollingTextData = [
|
||||||
const value = -1 * (this.armorChange.value - changes.system.changes[0].value);
|
getScrollTextData(this.parent.actor, changes.system.changes[0], 'armor')
|
||||||
options.scrollingTextData = [getScrollTextData(increased, value, 'armor')];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import DHAdversarySettings from '../../applications/sheets-configs/adversary-set
|
||||||
import { ActionField } from '../fields/actionField.mjs';
|
import { ActionField } from '../fields/actionField.mjs';
|
||||||
import { commonActorRules } from './base.mjs';
|
import { commonActorRules } from './base.mjs';
|
||||||
import DhCreature from './creature.mjs';
|
import DhCreature from './creature.mjs';
|
||||||
import { resourceField, bonusField } from '../fields/actorField.mjs';
|
import { bonusField } from '../fields/actorField.mjs';
|
||||||
import { calculateExpectedValue, parseTermsFromSimpleFormula } from '../../helpers/utils.mjs';
|
import { calculateExpectedValue, parseTermsFromSimpleFormula } from '../../helpers/utils.mjs';
|
||||||
import { adversaryExpectedDamage, adversaryScalingData } from '../../config/actorConfig.mjs';
|
import { adversaryExpectedDamage, adversaryScalingData } from '../../config/actorConfig.mjs';
|
||||||
|
|
||||||
|
|
@ -65,10 +65,6 @@ export default class DhpAdversary extends DhCreature {
|
||||||
label: 'DAGGERHEART.GENERAL.DamageThresholds.severeThreshold'
|
label: 'DAGGERHEART.GENERAL.DamageThresholds.severeThreshold'
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
resources: new fields.SchemaField({
|
|
||||||
hitPoints: resourceField(0, 0, 'DAGGERHEART.GENERAL.HitPoints.plural', true),
|
|
||||||
stress: resourceField(0, 0, 'DAGGERHEART.GENERAL.stress', true)
|
|
||||||
}),
|
|
||||||
rules: new fields.SchemaField({
|
rules: new fields.SchemaField({
|
||||||
...commonActorRules()
|
...commonActorRules()
|
||||||
}),
|
}),
|
||||||
|
|
@ -89,14 +85,14 @@ export default class DhpAdversary extends DhCreature {
|
||||||
type: 'attack'
|
type: 'attack'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
hitPoints: {
|
||||||
type: ['physical'],
|
type: ['physical'],
|
||||||
value: {
|
value: {
|
||||||
multiplier: 'flat'
|
multiplier: 'flat'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
@ -191,6 +187,7 @@ export default class DhpAdversary extends DhCreature {
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareDerivedData() {
|
prepareDerivedData() {
|
||||||
|
super.prepareDerivedData();
|
||||||
this.attack.roll.isStandardAttack = true;
|
this.attack.roll.isStandardAttack = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -268,12 +265,12 @@ export default class DhpAdversary extends DhCreature {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update damage in item actions
|
// Update damage in item actions
|
||||||
for (const action of Object.values(item.system.actions)) {
|
|
||||||
if (!action.damage) continue;
|
|
||||||
|
|
||||||
// Parse damage, and convert all formula matches in the descriptions to the new damage
|
// Parse damage, and convert all formula matches in the descriptions to the new damage
|
||||||
|
for (const action of Object.values(item.system.actions)) {
|
||||||
try {
|
try {
|
||||||
const result = this.#adjustActionDamage(action, { ...damageMeta, type: 'action' });
|
const result = this.#adjustActionDamage(action, { ...damageMeta, type: 'action' });
|
||||||
|
if (!result) continue;
|
||||||
|
|
||||||
for (const { previousFormula, formula } of Object.values(result)) {
|
for (const { previousFormula, formula } of Object.values(result)) {
|
||||||
const oldFormulaRegexp = new RegExp(
|
const oldFormulaRegexp = new RegExp(
|
||||||
previousFormula.replace(' ', '').replace('+', '(?:\\s)?\\+(?:\\s)?')
|
previousFormula.replace(' ', '').replace('+', '(?:\\s)?\\+(?:\\s)?')
|
||||||
|
|
@ -375,16 +372,14 @@ export default class DhpAdversary extends DhCreature {
|
||||||
/**
|
/**
|
||||||
* Updates damage to reflect a specific value.
|
* Updates damage to reflect a specific value.
|
||||||
* @throws if damage structure is invalid for conversion
|
* @throws if damage structure is invalid for conversion
|
||||||
* @returns the converted formula and value as a simplified term
|
* @returns the converted formula and value as a simplified term, or null if it doesn't deal HP damage
|
||||||
*/
|
*/
|
||||||
#adjustActionDamage(action, damageMeta) {
|
#adjustActionDamage(action, damageMeta) {
|
||||||
// The current algorithm only returns a value if there is a single damage part
|
if (!action.damage?.parts.hitPoints) return null;
|
||||||
const hpDamageParts = action.damage.parts.filter(d => d.applyTo === 'hitPoints');
|
|
||||||
if (hpDamageParts.length !== 1) throw new Error('incorrect number of hp parts');
|
|
||||||
|
|
||||||
const result = {};
|
const result = {};
|
||||||
for (const property of ['value', 'valueAlt']) {
|
for (const property of ['value', 'valueAlt']) {
|
||||||
const data = hpDamageParts[0][property];
|
const data = action.damage.parts.hitPoints[property];
|
||||||
const previousFormula = data.custom.enabled
|
const previousFormula = data.custom.enabled
|
||||||
? data.custom.formula
|
? data.custom.formula
|
||||||
: [data.flatMultiplier ? `${data.flatMultiplier}${data.dice}` : 0, data.bonus ?? 0]
|
: [data.flatMultiplier ? `${data.flatMultiplier}${data.dice}` : 0, data.bonus ?? 0]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import DHBaseActorSettings from '../../applications/sheets/api/actor-setting.mjs';
|
import DHBaseActorSettings from '../../applications/sheets/api/actor-setting.mjs';
|
||||||
import DHItem from '../../documents/item.mjs';
|
import DHItem from '../../documents/item.mjs';
|
||||||
import { getResourceScrollTextData } from '../../helpers/utils.mjs';
|
import { getScrollTextData } from '../../helpers/utils.mjs';
|
||||||
|
|
||||||
const fields = foundry.data.fields;
|
const fields = foundry.data.fields;
|
||||||
|
|
||||||
|
|
@ -211,7 +211,7 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
|
||||||
const textData = Object.keys(changes.system.resources).reduce((acc, key) => {
|
const textData = Object.keys(changes.system.resources).reduce((acc, key) => {
|
||||||
const resource = changes.system.resources[key];
|
const resource = changes.system.resources[key];
|
||||||
if (resource.value !== undefined && resource.value !== this.resources[key].value) {
|
if (resource.value !== undefined && resource.value !== this.resources[key].value) {
|
||||||
acc.push(getResourceScrollTextData(this.resources, resource, key));
|
acc.push(getScrollTextData(this.parent, resource, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs';
|
||||||
import DhLevelData from '../levelData.mjs';
|
import DhLevelData from '../levelData.mjs';
|
||||||
import { commonActorRules } from './base.mjs';
|
import { commonActorRules } from './base.mjs';
|
||||||
import DhCreature from './creature.mjs';
|
import DhCreature from './creature.mjs';
|
||||||
import { attributeField, resourceField, stressDamageReductionRule, bonusField } from '../fields/actorField.mjs';
|
import { attributeField, stressDamageReductionRule, bonusField } from '../fields/actorField.mjs';
|
||||||
import { ActionField } from '../fields/actionField.mjs';
|
import { ActionField } from '../fields/actionField.mjs';
|
||||||
import DHCharacterSettings from '../../applications/sheets-configs/character-settings.mjs';
|
import DHCharacterSettings from '../../applications/sheets-configs/character-settings.mjs';
|
||||||
|
|
||||||
|
|
@ -27,28 +27,6 @@ export default class DhCharacter extends DhCreature {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...super.defineSchema(),
|
...super.defineSchema(),
|
||||||
resources: new fields.SchemaField({
|
|
||||||
hitPoints: resourceField(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
'DAGGERHEART.GENERAL.HitPoints.plural',
|
|
||||||
true,
|
|
||||||
'DAGGERHEART.ACTORS.Character.maxHPBonus'
|
|
||||||
),
|
|
||||||
stress: resourceField(6, 0, 'DAGGERHEART.GENERAL.stress', true),
|
|
||||||
hope: new fields.SchemaField(
|
|
||||||
{
|
|
||||||
value: new fields.NumberField({
|
|
||||||
initial: 2,
|
|
||||||
min: 0,
|
|
||||||
integer: true,
|
|
||||||
label: 'DAGGERHEART.GENERAL.hope'
|
|
||||||
}),
|
|
||||||
isReversed: new fields.BooleanField({ initial: false })
|
|
||||||
},
|
|
||||||
{ label: 'DAGGERHEART.GENERAL.hope' }
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
traits: new fields.SchemaField({
|
traits: new fields.SchemaField({
|
||||||
agility: attributeField('DAGGERHEART.CONFIG.Traits.agility.name'),
|
agility: attributeField('DAGGERHEART.CONFIG.Traits.agility.name'),
|
||||||
strength: attributeField('DAGGERHEART.CONFIG.Traits.strength.name'),
|
strength: attributeField('DAGGERHEART.CONFIG.Traits.strength.name'),
|
||||||
|
|
@ -131,8 +109,8 @@ export default class DhCharacter extends DhCreature {
|
||||||
trait: 'strength'
|
trait: 'strength'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
hitPoints: {
|
||||||
type: ['physical'],
|
type: ['physical'],
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
|
|
@ -141,7 +119,7 @@ export default class DhCharacter extends DhCreature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
@ -686,6 +664,7 @@ export default class DhCharacter extends DhCreature {
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareBaseData() {
|
prepareBaseData() {
|
||||||
|
super.prepareBaseData();
|
||||||
this.evasion += this.class.value?.system?.evasion ?? 0;
|
this.evasion += this.class.value?.system?.evasion ?? 0;
|
||||||
|
|
||||||
const currentLevel = this.levelData.level.current;
|
const currentLevel = this.levelData.level.current;
|
||||||
|
|
@ -755,6 +734,7 @@ export default class DhCharacter extends DhCreature {
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareDerivedData() {
|
prepareDerivedData() {
|
||||||
|
super.prepareDerivedData();
|
||||||
let baseHope = this.resources.hope.value;
|
let baseHope = this.resources.hope.value;
|
||||||
if (this.companion) {
|
if (this.companion) {
|
||||||
for (let levelKey in this.companion.system.levelData.levelups) {
|
for (let levelKey in this.companion.system.levelData.levelups) {
|
||||||
|
|
@ -775,10 +755,11 @@ export default class DhCharacter extends DhCreature {
|
||||||
|
|
||||||
this.resources.armor = {
|
this.resources.armor = {
|
||||||
...this.armorScore,
|
...this.armorScore,
|
||||||
|
label: 'DAGGERHEART.GENERAL.armor',
|
||||||
isReversed: true
|
isReversed: true
|
||||||
};
|
};
|
||||||
|
|
||||||
this.attack.damage.parts[0].value.custom.formula = `@prof${this.basicAttackDamageDice}${this.rules.attack.damage.bonus ? ` + ${this.rules.attack.damage.bonus}` : ''}`;
|
this.attack.damage.parts.hitPoints.value.custom.formula = `@prof${this.basicAttackDamageDice}${this.rules.attack.damage.bonus ? ` + ${this.rules.attack.damage.bonus}` : ''}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRollData() {
|
getRollData() {
|
||||||
|
|
@ -814,7 +795,8 @@ export default class DhCharacter extends DhCreature {
|
||||||
const newHopeMax = this.system.resources.hope.max + diff;
|
const newHopeMax = this.system.resources.hope.max + diff;
|
||||||
const newHopeValue = Math.min(newHopeMax, this.system.resources.hope.value);
|
const newHopeValue = Math.min(newHopeMax, this.system.resources.hope.value);
|
||||||
if (newHopeValue != this.system.resources.hope.value) {
|
if (newHopeValue != this.system.resources.hope.value) {
|
||||||
if (!changes.system.resources) changes.system.resources = { hope: { value: 0 } };
|
if (!changes.system.resources.hope) changes.system.resources.hope = { value: 0 };
|
||||||
|
|
||||||
changes.system.resources.hope = {
|
changes.system.resources.hope = {
|
||||||
...changes.system.resources.hope,
|
...changes.system.resources.hope,
|
||||||
value: changes.system.resources.hope.value + newHopeValue
|
value: changes.system.resources.hope.value + newHopeValue
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs';
|
||||||
import { ActionField } from '../fields/actionField.mjs';
|
import { ActionField } from '../fields/actionField.mjs';
|
||||||
import { adjustDice, adjustRange } from '../../helpers/utils.mjs';
|
import { adjustDice, adjustRange } from '../../helpers/utils.mjs';
|
||||||
import DHCompanionSettings from '../../applications/sheets-configs/companion-settings.mjs';
|
import DHCompanionSettings from '../../applications/sheets-configs/companion-settings.mjs';
|
||||||
import { resourceField, bonusField } from '../fields/actorField.mjs';
|
import { bonusField } from '../fields/actorField.mjs';
|
||||||
|
|
||||||
export default class DhCompanion extends DhCreature {
|
export default class DhCompanion extends DhCreature {
|
||||||
static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Companion'];
|
static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Companion'];
|
||||||
|
|
@ -26,10 +26,6 @@ export default class DhCompanion extends DhCreature {
|
||||||
return {
|
return {
|
||||||
...super.defineSchema(),
|
...super.defineSchema(),
|
||||||
partner: new ForeignDocumentUUIDField({ type: 'Actor' }),
|
partner: new ForeignDocumentUUIDField({ type: 'Actor' }),
|
||||||
resources: new fields.SchemaField({
|
|
||||||
stress: resourceField(3, 0, 'DAGGERHEART.GENERAL.stress', true),
|
|
||||||
hope: new fields.NumberField({ initial: 0, integer: true, label: 'DAGGERHEART.GENERAL.hope' })
|
|
||||||
}),
|
|
||||||
evasion: new fields.NumberField({
|
evasion: new fields.NumberField({
|
||||||
required: true,
|
required: true,
|
||||||
min: 1,
|
min: 1,
|
||||||
|
|
@ -85,15 +81,15 @@ export default class DhCompanion extends DhCreature {
|
||||||
bonus: 0
|
bonus: 0
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
hitPoints: {
|
||||||
type: ['physical'],
|
type: ['physical'],
|
||||||
value: {
|
value: {
|
||||||
dice: 'd6',
|
dice: 'd6',
|
||||||
multiplier: 'prof'
|
multiplier: 'prof'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
@ -127,6 +123,7 @@ export default class DhCompanion extends DhCreature {
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareBaseData() {
|
prepareBaseData() {
|
||||||
|
super.prepareBaseData();
|
||||||
this.attack.roll.bonus = this.partner?.system?.spellcastModifier ?? 0;
|
this.attack.roll.bonus = this.partner?.system?.spellcastModifier ?? 0;
|
||||||
|
|
||||||
for (let levelKey in this.levelData.levelups) {
|
for (let levelKey in this.levelData.levelups) {
|
||||||
|
|
@ -138,7 +135,9 @@ export default class DhCompanion extends DhCreature {
|
||||||
break;
|
break;
|
||||||
case 'vicious':
|
case 'vicious':
|
||||||
if (selection.data[0] === 'damage') {
|
if (selection.data[0] === 'damage') {
|
||||||
this.attack.damage.parts[0].value.dice = adjustDice(this.attack.damage.parts[0].value.dice);
|
this.attack.damage.parts.hitPoints.value.dice = adjustDice(
|
||||||
|
this.attack.damage.parts.hitPoints.value.dice
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.attack.range = adjustRange(this.attack.range).id;
|
this.attack.range = adjustRange(this.attack.range).id;
|
||||||
}
|
}
|
||||||
|
|
@ -161,6 +160,7 @@ export default class DhCompanion extends DhCreature {
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareDerivedData() {
|
prepareDerivedData() {
|
||||||
|
super.prepareDerivedData();
|
||||||
/* Partner Related Setup */
|
/* Partner Related Setup */
|
||||||
if (this.partner) {
|
if (this.partner) {
|
||||||
this.levelData.level.changed = this.partner.system.levelData.level.current;
|
this.levelData.level.changed = this.partner.system.levelData.level.current;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { ResourcesField } from '../fields/actorField.mjs';
|
||||||
import BaseDataActor from './base.mjs';
|
import BaseDataActor from './base.mjs';
|
||||||
|
|
||||||
export default class DhCreature extends BaseDataActor {
|
export default class DhCreature extends BaseDataActor {
|
||||||
|
|
@ -7,6 +8,7 @@ export default class DhCreature extends BaseDataActor {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...super.defineSchema(),
|
...super.defineSchema(),
|
||||||
|
resources: new ResourcesField(this.metadata.type),
|
||||||
advantageSources: new fields.ArrayField(new fields.StringField(), {
|
advantageSources: new fields.ArrayField(new fields.StringField(), {
|
||||||
label: 'DAGGERHEART.ACTORS.Character.advantageSources.label',
|
label: 'DAGGERHEART.ACTORS.Character.advantageSources.label',
|
||||||
hint: 'DAGGERHEART.ACTORS.Character.advantageSources.hint'
|
hint: 'DAGGERHEART.ACTORS.Character.advantageSources.hint'
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ export default class DhEnvironment extends BaseDataActor {
|
||||||
potentialAdversaries: new fields.TypedObjectField(
|
potentialAdversaries: new fields.TypedObjectField(
|
||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
label: new fields.StringField(),
|
label: new fields.StringField(),
|
||||||
adversaries: new ForeignDocumentUUIDArrayField({ type: 'Actor' }, { required: false, initial: [] })
|
adversaries: new ForeignDocumentUUIDArrayField({ type: 'Actor' })
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
notes: new fields.HTMLField()
|
notes: new fields.HTMLField()
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
export { ActionCollection } from './actionField.mjs';
|
export { ActionCollection } from './actionField.mjs';
|
||||||
|
export { default as IterableTypedObjectField } from './iterableTypedObjectField.mjs';
|
||||||
export { default as FormulaField } from './formulaField.mjs';
|
export { default as FormulaField } from './formulaField.mjs';
|
||||||
export { default as ForeignDocumentUUIDField } from './foreignDocumentUUIDField.mjs';
|
export { default as ForeignDocumentUUIDField } from './foreignDocumentUUIDField.mjs';
|
||||||
export { default as ForeignDocumentUUIDArrayField } from './foreignDocumentUUIDArrayField.mjs';
|
export { default as ForeignDocumentUUIDArrayField } from './foreignDocumentUUIDArrayField.mjs';
|
||||||
|
|
|
||||||
|
|
@ -10,3 +10,4 @@ export { default as DamageField } from './damageField.mjs';
|
||||||
export { default as RollField } from './rollField.mjs';
|
export { default as RollField } from './rollField.mjs';
|
||||||
export { default as MacroField } from './macroField.mjs';
|
export { default as MacroField } from './macroField.mjs';
|
||||||
export { default as SummonField } from './summonField.mjs';
|
export { default as SummonField } from './summonField.mjs';
|
||||||
|
export { default as TransformField } from './transformField.mjs';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import FormulaField from '../formulaField.mjs';
|
import FormulaField from '../formulaField.mjs';
|
||||||
import { setsEqual } from '../../../helpers/utils.mjs';
|
import { setsEqual } from '../../../helpers/utils.mjs';
|
||||||
|
import IterableTypedObjectField from '../iterableTypedObjectField.mjs';
|
||||||
|
|
||||||
const fields = foundry.data.fields;
|
const fields = foundry.data.fields;
|
||||||
|
|
||||||
|
|
@ -12,7 +13,7 @@ export default class DamageField extends fields.SchemaField {
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
constructor(options, context = {}) {
|
constructor(options, context = {}) {
|
||||||
const damageFields = {
|
const damageFields = {
|
||||||
parts: new fields.ArrayField(new fields.EmbeddedDataField(DHDamageData)),
|
parts: new IterableTypedObjectField(DHDamageData),
|
||||||
includeBase: new fields.BooleanField({
|
includeBase: new fields.BooleanField({
|
||||||
initial: false,
|
initial: false,
|
||||||
label: 'DAGGERHEART.ACTIONS.Settings.includeBase.label'
|
label: 'DAGGERHEART.ACTIONS.Settings.includeBase.label'
|
||||||
|
|
|
||||||
103
module/data/fields/action/transformField.mjs
Normal file
103
module/data/fields/action/transformField.mjs
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
|
||||||
|
export default class DHSummonField extends fields.SchemaField {
|
||||||
|
/**
|
||||||
|
* Action Workflow order
|
||||||
|
*/
|
||||||
|
static order = 130;
|
||||||
|
|
||||||
|
constructor(options = {}, context = {}) {
|
||||||
|
const transformFields = {
|
||||||
|
actorUUID: new fields.DocumentUUIDField({
|
||||||
|
type: 'Actor',
|
||||||
|
required: true
|
||||||
|
}),
|
||||||
|
resourceRefresh: new fields.SchemaField({
|
||||||
|
hitPoints: new fields.BooleanField({ initial: true }),
|
||||||
|
stress: new fields.BooleanField({ initial: true })
|
||||||
|
})
|
||||||
|
};
|
||||||
|
super(transformFields, options, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async execute() {
|
||||||
|
if (!this.transform.actorUUID) {
|
||||||
|
ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.noTransformActor'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseActor = await foundry.utils.fromUuid(this.transform.actorUUID);
|
||||||
|
if (!baseActor) {
|
||||||
|
ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.transformActorMissing'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canvas.scene) {
|
||||||
|
ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.canvasError'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.actor.prototypeToken.actorLink) {
|
||||||
|
ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.actorLinkError'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.actor.token) {
|
||||||
|
ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.prototypeError'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const actor = await DHSummonField.getWorldActor(baseActor);
|
||||||
|
const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes;
|
||||||
|
const tokenSize = actor?.system.metadata.usesSize ? tokenSizes[actor.system.size] : actor.prototypeToken.width;
|
||||||
|
|
||||||
|
await this.actor.token.update(
|
||||||
|
{ ...actor.prototypeToken.toJSON(), actorId: actor.id, width: tokenSize, height: tokenSize },
|
||||||
|
{ diff: false, recursive: false, noHook: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (this.actor.token.combatant) {
|
||||||
|
this.actor.token.combatant.update({ actorId: actor.id, img: actor.prototypeToken.texture.src });
|
||||||
|
}
|
||||||
|
|
||||||
|
const marks = { hitPoints: 0, stress: 0 };
|
||||||
|
if (!this.transform.resourceRefresh.hitPoints) {
|
||||||
|
marks.hitPoints = Math.min(
|
||||||
|
this.actor.system.resources.hitPoints.value,
|
||||||
|
this.actor.token.actor.system.resources.hitPoints.max - 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!this.transform.resourceRefresh.stress) {
|
||||||
|
marks.stress = Math.min(
|
||||||
|
this.actor.system.resources.stress.value,
|
||||||
|
this.actor.token.actor.system.resources.stress.max - 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (marks.hitPoints || marks.stress) {
|
||||||
|
this.actor.token.actor.update({
|
||||||
|
'system.resources': {
|
||||||
|
hitPoints: { value: marks.hitPoints },
|
||||||
|
stress: { value: marks.stress }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const prevPosition = { ...this.actor.sheet.position };
|
||||||
|
this.actor.sheet.close();
|
||||||
|
this.actor.token.actor.sheet.render({ force: true, position: prevPosition });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for any available instances of the actor present in the world, or create a world actor based on compendium */
|
||||||
|
static async getWorldActor(baseActor) {
|
||||||
|
if (!baseActor.inCompendium) return baseActor;
|
||||||
|
|
||||||
|
const dataType = game.system.api.data.actors[`Dh${baseActor.type.capitalize()}`];
|
||||||
|
if (dataType && baseActor.img === dataType.DEFAULT_ICON) {
|
||||||
|
const worldActorCopy = game.actors.find(x => x.name === baseActor.name);
|
||||||
|
if (worldActorCopy) return worldActorCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
const worldActor = await game.system.api.documents.DhpActor.create(baseActor.toObject());
|
||||||
|
return worldActor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -87,10 +87,10 @@ export class ActionField extends foundry.data.fields.ObjectField {
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
_cleanType(value, options) {
|
_cleanType(value, options, _state) {
|
||||||
if (!(typeof value === 'object')) value = {};
|
if (!(typeof value === 'object')) value = {};
|
||||||
const cls = this.getModel(value);
|
const cls = this.getModel(value);
|
||||||
if (cls) return cls.cleanData(value, options);
|
if (cls) return cls.cleanData(value, options, _state);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,22 +6,6 @@ const attributeField = label =>
|
||||||
tierMarked: new fields.BooleanField({ initial: false })
|
tierMarked: new fields.BooleanField({ initial: false })
|
||||||
});
|
});
|
||||||
|
|
||||||
const resourceField = (max = 0, initial = 0, label, reverse = false, maxLabel) =>
|
|
||||||
new fields.SchemaField(
|
|
||||||
{
|
|
||||||
value: new fields.NumberField({ initial: initial, min: 0, integer: true, label }),
|
|
||||||
max: new fields.NumberField({
|
|
||||||
initial: max,
|
|
||||||
integer: true,
|
|
||||||
label:
|
|
||||||
maxLabel ??
|
|
||||||
game.i18n.format('DAGGERHEART.GENERAL.maxWithThing', { thing: game.i18n.localize(label) })
|
|
||||||
}),
|
|
||||||
isReversed: new fields.BooleanField({ initial: reverse })
|
|
||||||
},
|
|
||||||
{ label }
|
|
||||||
);
|
|
||||||
|
|
||||||
const stressDamageReductionRule = localizationPath =>
|
const stressDamageReductionRule = localizationPath =>
|
||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
cost: new fields.NumberField({
|
cost: new fields.NumberField({
|
||||||
|
|
@ -37,4 +21,67 @@ const bonusField = label =>
|
||||||
dice: new fields.ArrayField(new fields.StringField(), { label: `${game.i18n.localize(label)} Dice` })
|
dice: new fields.ArrayField(new fields.StringField(), { label: `${game.i18n.localize(label)} Dice` })
|
||||||
});
|
});
|
||||||
|
|
||||||
export { attributeField, resourceField, stressDamageReductionRule, bonusField };
|
/**
|
||||||
|
* Field used for actor resources. It is a resource that validates dynamically based on the config.
|
||||||
|
* Because "max" may be defined during runtime, we don't attempt to clamp the maximum value.
|
||||||
|
*/
|
||||||
|
class ResourcesField extends fields.TypedObjectField {
|
||||||
|
constructor(actorType) {
|
||||||
|
super(
|
||||||
|
new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ min: 0, initial: 0, integer: true }),
|
||||||
|
// Some resources allow changing max. A null max means its the default
|
||||||
|
max: new fields.NumberField({ initial: null, integer: true, nullable: true })
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.actorType = actorType;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInitialValue() {
|
||||||
|
const resources = CONFIG.DH.RESOURCE[this.actorType].all;
|
||||||
|
return Object.values(resources).reduce((result, resource) => {
|
||||||
|
result[resource.id] = {
|
||||||
|
value: resource.initial,
|
||||||
|
max: null
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
_validateKey(key) {
|
||||||
|
return key in CONFIG.DH.RESOURCE[this.actorType].all;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cleanType(value, options, _state) {
|
||||||
|
value = super._cleanType(value, options, _state);
|
||||||
|
|
||||||
|
// If not partial, ensure all data exists
|
||||||
|
if (!options.partial) {
|
||||||
|
value = foundry.utils.mergeObject(this.getInitialValue(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initializes the original source data, returning prepared data */
|
||||||
|
initialize(...args) {
|
||||||
|
const data = super.initialize(...args);
|
||||||
|
const resources = CONFIG.DH.RESOURCE[this.actorType].all;
|
||||||
|
for (const [key, value] of Object.entries(data)) {
|
||||||
|
// TypedObjectField only calls _validateKey when persisting, so we also call it here
|
||||||
|
if (!this._validateKey(key)) {
|
||||||
|
delete value[key];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add basic prepared data.
|
||||||
|
const resource = resources[key];
|
||||||
|
value.label = resource.label;
|
||||||
|
value.isReversed = resources[key].reverse;
|
||||||
|
value.max = typeof resource.max === 'number' ? (value.max ?? resource.max) : null;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { attributeField, ResourcesField, stressDamageReductionRule, bonusField };
|
||||||
|
|
|
||||||
32
module/data/fields/iterableTypedObjectField.mjs
Normal file
32
module/data/fields/iterableTypedObjectField.mjs
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
export default class IterableTypedObjectField extends foundry.data.fields.TypedObjectField {
|
||||||
|
constructor(model, options = { collectionClass: foundry.utils.Collection }, context = {}) {
|
||||||
|
super(new foundry.data.fields.EmbeddedDataField(model), options, context);
|
||||||
|
this.#elementClass = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elementClass;
|
||||||
|
|
||||||
|
/** Initializes an object with an iterator. This modifies the prototype instead of */
|
||||||
|
initialize(values) {
|
||||||
|
const object = Object.create(IterableObjectPrototype);
|
||||||
|
for (const [key, value] of Object.entries(values)) {
|
||||||
|
object[key] = new this.#elementClass(value);
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The prototype of an iterable object.
|
||||||
|
* This allows the functionality of a class but also allows foundry.utils.getType() to return "Object" instead of "Unknown".
|
||||||
|
*/
|
||||||
|
const IterableObjectPrototype = {
|
||||||
|
[Symbol.iterator]: function* () {
|
||||||
|
for (const value of Object.values(this)) {
|
||||||
|
yield value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
map: function (func) {
|
||||||
|
return Array.from(this, func);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
* @property {boolean} isInventoryItem- Indicates whether items of this type is a Inventory Item
|
* @property {boolean} isInventoryItem- Indicates whether items of this type is a Inventory Item
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { addLinkedItemsDiff, getResourceScrollTextData, updateLinkedItemApps } from '../../helpers/utils.mjs';
|
import { addLinkedItemsDiff, getScrollTextData, updateLinkedItemApps } from '../../helpers/utils.mjs';
|
||||||
import { ActionsField } from '../fields/actionField.mjs';
|
import { ActionsField } from '../fields/actionField.mjs';
|
||||||
import FormulaField from '../fields/formulaField.mjs';
|
import FormulaField from '../fields/formulaField.mjs';
|
||||||
|
|
||||||
|
|
@ -224,11 +224,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
|
||||||
const armorChanged =
|
const armorChanged =
|
||||||
changed.system?.marks?.value !== undefined && changed.system.marks.value !== this.marks.value;
|
changed.system?.marks?.value !== undefined && changed.system.marks.value !== this.marks.value;
|
||||||
if (armorChanged && autoSettings.resourceScrollTexts && this.parent.parent?.type === 'character') {
|
if (armorChanged && autoSettings.resourceScrollTexts && this.parent.parent?.type === 'character') {
|
||||||
const armorData = getResourceScrollTextData(
|
const armorData = getScrollTextData(this.parent.parent, changed.system.marks, 'armor');
|
||||||
this.parent.parent.system.resources,
|
|
||||||
changed.system.marks,
|
|
||||||
'armor'
|
|
||||||
);
|
|
||||||
options.scrollingTextData = [armorData];
|
options.scrollingTextData = [armorData];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,15 +63,15 @@ export default class DHWeapon extends AttachableItem {
|
||||||
type: 'attack'
|
type: 'attack'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: {
|
||||||
{
|
hitPoints: {
|
||||||
type: ['physical'],
|
type: ['physical'],
|
||||||
value: {
|
value: {
|
||||||
multiplier: 'prof',
|
multiplier: 'prof',
|
||||||
dice: 'd8'
|
dice: 'd8'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
@ -112,24 +112,14 @@ export default class DHWeapon extends AttachableItem {
|
||||||
async getDescriptionData() {
|
async getDescriptionData() {
|
||||||
const baseDescription = this.description;
|
const baseDescription = this.description;
|
||||||
|
|
||||||
const tier = game.i18n.localize(`DAGGERHEART.GENERAL.Tiers.${this.tier}`);
|
|
||||||
const trait = game.i18n.localize(CONFIG.DH.ACTOR.abilities[this.attack.roll.trait].label);
|
|
||||||
const range = game.i18n.localize(`DAGGERHEART.CONFIG.Range.${this.attack.range}.name`);
|
|
||||||
const damage = Roll.replaceFormulaData(this.attack.damageFormula, this.parent.parent ?? this.parent);
|
|
||||||
const burden = game.i18n.localize(CONFIG.DH.GENERAL.burden[this.burden].label);
|
|
||||||
|
|
||||||
const allFeatures = CONFIG.DH.ITEM.allWeaponFeatures();
|
const allFeatures = CONFIG.DH.ITEM.allWeaponFeatures();
|
||||||
const features = this.weaponFeatures.map(x => allFeatures[x.value]).filter(x => x);
|
const features = this.weaponFeatures.map(x => allFeatures[x.value]).filter(x => x);
|
||||||
|
|
||||||
const prefix = await foundry.applications.handlebars.renderTemplate(
|
const prefix = await foundry.applications.handlebars.renderTemplate(
|
||||||
'systems/daggerheart/templates/sheets/items/weapon/description.hbs',
|
'systems/daggerheart/templates/sheets/items/weapon/description.hbs',
|
||||||
{
|
{
|
||||||
features,
|
item: this,
|
||||||
tier,
|
features
|
||||||
trait,
|
|
||||||
range,
|
|
||||||
damage,
|
|
||||||
burden
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,16 @@
|
||||||
export default class DhAppearance extends foundry.abstract.DataModel {
|
export default class DhAppearance extends foundry.abstract.DataModel {
|
||||||
static LOCALIZATION_PREFIXES = ['DAGGERHEART.SETTINGS.Appearance'];
|
static LOCALIZATION_PREFIXES = ['DAGGERHEART.SETTINGS.Appearance'];
|
||||||
|
|
||||||
|
static sfxSchema = () =>
|
||||||
|
new foundry.data.fields.SchemaField({
|
||||||
|
class: new foundry.data.fields.StringField({
|
||||||
|
nullable: true,
|
||||||
|
initial: null,
|
||||||
|
blank: true,
|
||||||
|
choices: CONFIG.DH.GENERAL.diceSoNiceSFXClasses
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
static defineSchema() {
|
static defineSchema() {
|
||||||
const { StringField, ColorField, BooleanField, SchemaField } = foundry.data.fields;
|
const { StringField, ColorField, BooleanField, SchemaField } = foundry.data.fields;
|
||||||
|
|
||||||
|
|
@ -15,7 +25,10 @@ export default class DhAppearance extends foundry.abstract.DataModel {
|
||||||
colorset: new StringField({ initial: 'inspired', required: true, blank: false }),
|
colorset: new StringField({ initial: 'inspired', required: true, blank: false }),
|
||||||
material: new StringField({ initial: 'metal', required: true, blank: false }),
|
material: new StringField({ initial: 'metal', required: true, blank: false }),
|
||||||
system: new StringField({ initial: 'standard', required: true, blank: false }),
|
system: new StringField({ initial: 'standard', required: true, blank: false }),
|
||||||
font: new StringField({ initial: 'auto', required: true, blank: false })
|
font: new StringField({ initial: 'auto', required: true, blank: false }),
|
||||||
|
sfx: new SchemaField({
|
||||||
|
higher: DhAppearance.sfxSchema()
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -30,7 +43,10 @@ export default class DhAppearance extends foundry.abstract.DataModel {
|
||||||
hope: diceStyle({ fg: '#ffffff', bg: '#ffe760', outline: '#000000', edge: '#ffffff' }),
|
hope: diceStyle({ fg: '#ffffff', bg: '#ffe760', outline: '#000000', edge: '#ffffff' }),
|
||||||
fear: diceStyle({ fg: '#000000', bg: '#0032b1', outline: '#ffffff', edge: '#000000' }),
|
fear: diceStyle({ fg: '#000000', bg: '#0032b1', outline: '#ffffff', edge: '#000000' }),
|
||||||
advantage: diceStyle({ fg: '#ffffff', bg: '#008000', outline: '#000000', edge: '#ffffff' }),
|
advantage: diceStyle({ fg: '#ffffff', bg: '#008000', outline: '#000000', edge: '#ffffff' }),
|
||||||
disadvantage: diceStyle({ fg: '#000000', bg: '#b30000', outline: '#ffffff', edge: '#000000' })
|
disadvantage: diceStyle({ fg: '#000000', bg: '#b30000', outline: '#ffffff', edge: '#000000' }),
|
||||||
|
sfx: new SchemaField({
|
||||||
|
critical: DhAppearance.sfxSchema()
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
extendCharacterDescriptions: new BooleanField(),
|
extendCharacterDescriptions: new BooleanField(),
|
||||||
extendAdversaryDescriptions: new BooleanField(),
|
extendAdversaryDescriptions: new BooleanField(),
|
||||||
|
|
@ -65,4 +81,48 @@ export default class DhAppearance extends foundry.abstract.DataModel {
|
||||||
showGenericStatusEffects: new BooleanField({ initial: true })
|
showGenericStatusEffects: new BooleanField({ initial: true })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get diceSoNiceData() {
|
||||||
|
const globalOverrides = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.GlobalOverrides);
|
||||||
|
const getSFX = (baseClientData, overrideKey) => {
|
||||||
|
if (!globalOverrides.diceSoNice.sfx.overrideEnabled) return baseClientData;
|
||||||
|
const overrideData = globalOverrides.diceSoNice.sfx[overrideKey];
|
||||||
|
const clientData = foundry.utils.deepClone(baseClientData);
|
||||||
|
return Object.keys(clientData).reduce((acc, key) => {
|
||||||
|
const data = clientData[key];
|
||||||
|
acc[key] = Object.keys(data).reduce((acc, dataKey) => {
|
||||||
|
const value = data[dataKey];
|
||||||
|
acc[dataKey] = value ? value : overrideData[key][dataKey];
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...this.diceSoNice,
|
||||||
|
sfx: getSFX(this.diceSoNice.sfx, 'global'),
|
||||||
|
hope: {
|
||||||
|
...this.diceSoNice.hope,
|
||||||
|
sfx: getSFX(this.diceSoNice.hope.sfx, 'hope')
|
||||||
|
},
|
||||||
|
fear: {
|
||||||
|
...this.diceSoNice.fear,
|
||||||
|
sfx: getSFX(this.diceSoNice.fear.sfx, 'fear')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Invoked by the setting when data changes */
|
||||||
|
handleChange() {
|
||||||
|
if (this.displayFear) {
|
||||||
|
if (ui.resources) {
|
||||||
|
if (this.displayFear === 'hide') ui.resources.close({ allowed: true });
|
||||||
|
else ui.resources.render({ force: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const globalOverrides = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.GlobalOverrides);
|
||||||
|
globalOverrides.diceSoNiceSFXUpdate(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
55
module/data/settings/GlobalOverrides.mjs
Normal file
55
module/data/settings/GlobalOverrides.mjs
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
import DhAppearance from './Appearance.mjs';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A setting to handle cases where we want to allow the GM to set a global default for client settings.
|
||||||
|
*/
|
||||||
|
export default class DhGlobalOverrides extends foundry.abstract.DataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
diceSoNice: new fields.SchemaField({
|
||||||
|
sfx: new fields.SchemaField({
|
||||||
|
overrideEnabled: new fields.BooleanField(),
|
||||||
|
global: new fields.SchemaField({
|
||||||
|
critical: DhAppearance.sfxSchema()
|
||||||
|
}),
|
||||||
|
hope: new fields.SchemaField({
|
||||||
|
higher: DhAppearance.sfxSchema()
|
||||||
|
}),
|
||||||
|
fear: new fields.SchemaField({
|
||||||
|
higher: DhAppearance.sfxSchema()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async diceSoNiceSFXUpdate(appearanceSettings, enabled) {
|
||||||
|
if (!game.user.isGM) return;
|
||||||
|
|
||||||
|
const newEnabled = enabled !== undefined ? enabled : this.diceSoNice.sfx.overrideEnabled;
|
||||||
|
if (newEnabled) {
|
||||||
|
const newOverrides = foundry.utils.mergeObject(this.toObject(), {
|
||||||
|
diceSoNice: {
|
||||||
|
sfx: {
|
||||||
|
overrideEnabled: true,
|
||||||
|
global: appearanceSettings.diceSoNice.sfx,
|
||||||
|
hope: appearanceSettings.diceSoNice.hope.sfx,
|
||||||
|
fear: appearanceSettings.diceSoNice.fear.sfx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.GlobalOverrides, newOverrides);
|
||||||
|
} else {
|
||||||
|
const newOverrides = {
|
||||||
|
...this.toObject(),
|
||||||
|
diceSoNice: {
|
||||||
|
sfx: {
|
||||||
|
overrideEnabled: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.GlobalOverrides, newOverrides);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -145,6 +145,16 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
|
||||||
description: new fields.StringField()
|
description: new fields.StringField()
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
resources: new fields.TypedObjectField(
|
||||||
|
new fields.SchemaField({
|
||||||
|
resources: new fields.TypedObjectField(new fields.EmbeddedDataField(Resource))
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
initial: {
|
||||||
|
character: { resources: {} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
itemFeatures: new fields.SchemaField({
|
itemFeatures: new fields.SchemaField({
|
||||||
weaponFeatures: new fields.TypedObjectField(
|
weaponFeatures: new fields.TypedObjectField(
|
||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
|
|
@ -185,4 +195,117 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
|
||||||
}
|
}
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Invoked by the setting when data changes */
|
||||||
|
handleChange() {
|
||||||
|
if (this.maxFear) {
|
||||||
|
if (ui.resources) ui.resources.render({ force: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.refreshConfig();
|
||||||
|
this.#resetActors();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Update config values based on homebrew data. Make sure the references don't change */
|
||||||
|
refreshConfig() {
|
||||||
|
for (const [actorType, actorData] of Object.entries(this.resources)) {
|
||||||
|
const config = CONFIG.DH.RESOURCE[actorType];
|
||||||
|
for (const key of Object.keys(config.all)) {
|
||||||
|
delete config.all[key];
|
||||||
|
}
|
||||||
|
Object.assign(config.all, {
|
||||||
|
...Object.entries(actorData.resources).reduce((result, [key, value]) => {
|
||||||
|
result[key] = value.toObject();
|
||||||
|
result[key].id = key;
|
||||||
|
return result;
|
||||||
|
}, {}),
|
||||||
|
...config.custom,
|
||||||
|
...config.base
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a reset and non-forced re-render on all given actors (if given)
|
||||||
|
* or all world actors and actors in all scenes to show immediate results for a changed setting.
|
||||||
|
*/
|
||||||
|
#resetActors() {
|
||||||
|
const actors = new Set(
|
||||||
|
[
|
||||||
|
game.actors.contents,
|
||||||
|
game.scenes.contents.flatMap(s => s.tokens.contents).flatMap(t => t.actor ?? [])
|
||||||
|
].flat()
|
||||||
|
);
|
||||||
|
for (const actor of actors) {
|
||||||
|
for (const app of Object.values(actor.apps)) {
|
||||||
|
for (const element of app.element?.querySelectorAll('prose-mirror.active')) {
|
||||||
|
element.open = false; // This triggers a save
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actor.reset();
|
||||||
|
actor.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Resource extends foundry.abstract.DataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
initial: new fields.NumberField({
|
||||||
|
required: true,
|
||||||
|
integer: true,
|
||||||
|
initial: 0,
|
||||||
|
min: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.initial'
|
||||||
|
}),
|
||||||
|
max: new fields.NumberField({
|
||||||
|
nullable: true,
|
||||||
|
initial: null,
|
||||||
|
min: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.max'
|
||||||
|
}),
|
||||||
|
label: new fields.StringField({ label: 'DAGGERHEART.GENERAL.label' }),
|
||||||
|
images: new fields.SchemaField({
|
||||||
|
full: imageIconField('fa solid fa-circle'),
|
||||||
|
empty: imageIconField('fa-regular fa-circle')
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static getDefaultResourceData = label => {
|
||||||
|
const images = Resource.schema.fields.images.getInitialValue();
|
||||||
|
return {
|
||||||
|
initial: 0,
|
||||||
|
max: 0,
|
||||||
|
label: label ?? '',
|
||||||
|
images
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
static getDefaultImageData = imageKey => {
|
||||||
|
return Resource.schema.fields.images.fields[imageKey].getInitialValue();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageIconField = defaultValue =>
|
||||||
|
new foundry.data.fields.SchemaField(
|
||||||
|
{
|
||||||
|
value: new foundry.data.fields.StringField({
|
||||||
|
initial: defaultValue,
|
||||||
|
label: 'DAGGERHEART.SETTINGS.Homebrew.FIELDS.resources.resources.value.label'
|
||||||
|
}),
|
||||||
|
isIcon: new foundry.data.fields.BooleanField({
|
||||||
|
required: true,
|
||||||
|
initial: true,
|
||||||
|
label: 'DAGGERHEART.SETTINGS.Homebrew.FIELDS.resources.resources.isIcon.label'
|
||||||
|
}),
|
||||||
|
noColorFilter: new foundry.data.fields.BooleanField({
|
||||||
|
required: true,
|
||||||
|
initial: false,
|
||||||
|
label: 'DAGGERHEART.SETTINGS.Homebrew.FIELDS.resources.resources.noColorFilter.label'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{ required: true }
|
||||||
|
);
|
||||||
|
|
|
||||||
12
module/data/settings/Metagaming.mjs
Normal file
12
module/data/settings/Metagaming.mjs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
export default class DhMetagaming extends foundry.abstract.DataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
hideObserverPermissionInChat: new fields.BooleanField({
|
||||||
|
initial: false,
|
||||||
|
label: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hideObserverPermissionInChat.label',
|
||||||
|
hint: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hideObserverPermissionInChat.hint'
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
export { default as DhAppearance } from './Appearance.mjs';
|
export { default as DhAppearance } from './Appearance.mjs';
|
||||||
export { default as DhAutomation } from './Automation.mjs';
|
export { default as DhAutomation } from './Automation.mjs';
|
||||||
export { default as DhHomebrew } from './Homebrew.mjs';
|
export { default as DhHomebrew } from './Homebrew.mjs';
|
||||||
|
export { default as DhMetagaming } from './Metagaming.mjs';
|
||||||
export { default as DhVariantRules } from './VariantRules.mjs';
|
export { default as DhVariantRules } from './VariantRules.mjs';
|
||||||
|
export { default as DhGlobalOverrides } from './GlobalOverrides.mjs';
|
||||||
|
|
|
||||||
|
|
@ -140,8 +140,14 @@ export default class DHRoll extends Roll {
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
async render({ flavor, template = this.constructor.CHAT_TEMPLATE, isPrivate = false, ...options } = {}) {
|
async render({ flavor, template = this.constructor.CHAT_TEMPLATE, isPrivate = false, ...options } = {}) {
|
||||||
if (!this._evaluated) return;
|
if (!this._evaluated) return;
|
||||||
|
|
||||||
|
const metagamingSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Metagaming);
|
||||||
const chatData = await this._prepareChatRenderContext({ flavor, isPrivate, ...options });
|
const chatData = await this._prepareChatRenderContext({ flavor, isPrivate, ...options });
|
||||||
return foundry.applications.handlebars.renderTemplate(template, chatData);
|
return foundry.applications.handlebars.renderTemplate(template, {
|
||||||
|
...chatData,
|
||||||
|
parent: chatData.parent,
|
||||||
|
metagamingSettings
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
|
|
|
||||||
|
|
@ -378,6 +378,8 @@ export default class DualityRoll extends D20Roll {
|
||||||
let parsedRoll = game.system.api.dice.DualityRoll.fromData({ ...rollString, evaluated: false });
|
let parsedRoll = game.system.api.dice.DualityRoll.fromData({ ...rollString, evaluated: false });
|
||||||
const term = parsedRoll.terms[target.dataset.dieIndex];
|
const term = parsedRoll.terms[target.dataset.dieIndex];
|
||||||
await term.reroll(`/r1=${term.total}`);
|
await term.reroll(`/r1=${term.total}`);
|
||||||
|
const result = await parsedRoll.evaluate();
|
||||||
|
|
||||||
if (game.modules.get('dice-so-nice')?.active) {
|
if (game.modules.get('dice-so-nice')?.active) {
|
||||||
const diceSoNiceRoll = {
|
const diceSoNiceRoll = {
|
||||||
_evaluated: true,
|
_evaluated: true,
|
||||||
|
|
@ -391,7 +393,7 @@ export default class DualityRoll extends D20Roll {
|
||||||
options: { appearance: {} }
|
options: { appearance: {} }
|
||||||
};
|
};
|
||||||
|
|
||||||
const diceSoNicePresets = await getDiceSoNicePresets(`d${term._faces}`, `d${term._faces}`);
|
const diceSoNicePresets = await getDiceSoNicePresets(result, `d${term._faces}`, `d${term._faces}`);
|
||||||
const type = target.dataset.type;
|
const type = target.dataset.type;
|
||||||
if (diceSoNicePresets[type]) {
|
if (diceSoNicePresets[type]) {
|
||||||
diceSoNiceRoll.dice[0].options = diceSoNicePresets[type];
|
diceSoNiceRoll.dice[0].options = diceSoNicePresets[type];
|
||||||
|
|
@ -400,8 +402,6 @@ export default class DualityRoll extends D20Roll {
|
||||||
await game.dice3d.showForRoll(diceSoNiceRoll, game.user, true);
|
await game.dice3d.showForRoll(diceSoNiceRoll, game.user, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
await parsedRoll.evaluate();
|
|
||||||
|
|
||||||
const newRoll = game.system.api.dice.DualityRoll.postEvaluate(parsedRoll, {
|
const newRoll = game.system.api.dice.DualityRoll.postEvaluate(parsedRoll, {
|
||||||
targets: message.system.targets,
|
targets: message.system.targets,
|
||||||
roll: {
|
roll: {
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,11 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
||||||
document = fromUuidSync(uuid);
|
document = fromUuidSync(uuid);
|
||||||
if (!document) return;
|
if (!document) return;
|
||||||
|
|
||||||
e.setAttribute('data-view-perm', document.testUserPermission(game.user, 'OBSERVER'));
|
|
||||||
e.setAttribute('data-use-perm', document.testUserPermission(game.user, 'OWNER'));
|
e.setAttribute('data-use-perm', document.testUserPermission(game.user, 'OWNER'));
|
||||||
|
|
||||||
|
const settings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Metagaming);
|
||||||
|
if (settings.hideObserverPermissionInChat)
|
||||||
|
e.setAttribute('data-view-perm', document.testUserPermission(game.user, 'OBSERVER'));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.isContentVisible) {
|
if (this.isContentVisible) {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { AdversaryBPPerEncounter, BaseBPPerEncounter } from '../config/encounter
|
||||||
export default class DhTooltipManager extends foundry.helpers.interaction.TooltipManager {
|
export default class DhTooltipManager extends foundry.helpers.interaction.TooltipManager {
|
||||||
#wide = false;
|
#wide = false;
|
||||||
#bordered = false;
|
#bordered = false;
|
||||||
|
#active = false;
|
||||||
|
|
||||||
async activate(element, options = {}) {
|
async activate(element, options = {}) {
|
||||||
const { TextEditor } = foundry.applications.ux;
|
const { TextEditor } = foundry.applications.ux;
|
||||||
|
|
@ -168,7 +169,100 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.activate(element, { ...options, html: html });
|
this.baseActivate(element, { ...options, html: html });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Need to pass more options to _setAnchor, so have to copy whole foundry method >_< */
|
||||||
|
async baseActivate(element, options) {
|
||||||
|
let { text, direction, cssClass, locked = false, html, content } = options;
|
||||||
|
if (content && !html) {
|
||||||
|
foundry.utils.logCompatibilityWarning(
|
||||||
|
'The content option has been deprecated in favor of the html option',
|
||||||
|
{ since: 13, until: 15, once: true }
|
||||||
|
);
|
||||||
|
html = content;
|
||||||
|
}
|
||||||
|
if (text && html) throw new Error('Cannot provide both text and html options to TooltipManager#activate.');
|
||||||
|
// Deactivate currently active element
|
||||||
|
this.deactivate();
|
||||||
|
// Check if the element still exists in the DOM.
|
||||||
|
if (!document.body.contains(element)) return;
|
||||||
|
// Mark the new element as active
|
||||||
|
this.#active = true;
|
||||||
|
this.element = element;
|
||||||
|
element.setAttribute('aria-describedby', 'tooltip');
|
||||||
|
html ||= element.dataset.tooltipHtml;
|
||||||
|
if (html) {
|
||||||
|
if (typeof html === 'string') this.tooltip.innerHTML = foundry.utils.cleanHTML(html);
|
||||||
|
else {
|
||||||
|
this.tooltip.innerHTML = ''; // Clear existing HTML
|
||||||
|
this.tooltip.appendChild(html);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text ||= element.dataset.tooltipText;
|
||||||
|
if (text) this.tooltip.textContent = text;
|
||||||
|
else {
|
||||||
|
text = element.dataset.tooltip;
|
||||||
|
// Localized message should be safe
|
||||||
|
if (game.i18n.has(text)) this.tooltip.innerHTML = game.i18n.localize(text);
|
||||||
|
else this.tooltip.innerHTML = foundry.utils.cleanHTML(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activate display of the tooltip
|
||||||
|
this.tooltip.removeAttribute('class');
|
||||||
|
this.tooltip.classList.add('active', 'themed', 'theme-dark');
|
||||||
|
this.tooltip.showPopover();
|
||||||
|
cssClass ??= element.closest('[data-tooltip-class]')?.dataset.tooltipClass;
|
||||||
|
if (cssClass) this.tooltip.classList.add(...cssClass.split(' '));
|
||||||
|
|
||||||
|
// Set tooltip position
|
||||||
|
direction ??= element.closest('[data-tooltip-direction]')?.dataset.tooltipDirection;
|
||||||
|
if (!direction) direction = this._determineDirection();
|
||||||
|
this._setAnchor(direction, options);
|
||||||
|
|
||||||
|
if (locked || element.dataset.hasOwnProperty('locked')) this.lockTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
_setAnchor(direction, options) {
|
||||||
|
const directions = this.constructor.TOOLTIP_DIRECTIONS;
|
||||||
|
const pad = this.constructor.TOOLTIP_MARGIN_PX;
|
||||||
|
const pos = this.element.getBoundingClientRect();
|
||||||
|
|
||||||
|
const { innerHeight, innerWidth } = this.tooltip.ownerDocument.defaultView;
|
||||||
|
const tooltipPadding = 16;
|
||||||
|
const horizontalOffset = options.noOffset ? tooltipPadding : this.tooltip.offsetWidth / 2 - pos.width / 2;
|
||||||
|
const verticalOffset = options.noOffset ? tooltipPadding : this.tooltip.offsetHeight / 2 - pos.height / 2;
|
||||||
|
|
||||||
|
const style = {};
|
||||||
|
switch (direction) {
|
||||||
|
case directions.DOWN:
|
||||||
|
style.textAlign = 'center';
|
||||||
|
style.left = pos.left - horizontalOffset;
|
||||||
|
style.top = pos.bottom + pad;
|
||||||
|
break;
|
||||||
|
case directions.LEFT:
|
||||||
|
style.textAlign = 'left';
|
||||||
|
style.right = innerWidth - pos.left + pad;
|
||||||
|
style.top = pos.top - verticalOffset;
|
||||||
|
break;
|
||||||
|
case directions.RIGHT:
|
||||||
|
style.textAlign = 'right';
|
||||||
|
style.left = pos.right + pad;
|
||||||
|
style.top = pos.top - verticalOffset;
|
||||||
|
break;
|
||||||
|
case directions.UP:
|
||||||
|
style.textAlign = 'center';
|
||||||
|
style.left = pos.left - horizontalOffset;
|
||||||
|
style.bottom = innerHeight - pos.top + pad;
|
||||||
|
break;
|
||||||
|
case directions.CENTER:
|
||||||
|
style.textAlign = 'center';
|
||||||
|
style.left = pos.left - horizontalOffset;
|
||||||
|
style.top = pos.top - verticalOffset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return this._setStyle(style);
|
||||||
}
|
}
|
||||||
|
|
||||||
_determineItemTooltipDirection(element, prefered = this.constructor.TOOLTIP_DIRECTIONS.LEFT) {
|
_determineItemTooltipDirection(element, prefered = this.constructor.TOOLTIP_DIRECTIONS.LEFT) {
|
||||||
|
|
@ -270,6 +364,12 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**@inheritdoc */
|
||||||
|
dismissLockedTooltips() {
|
||||||
|
super.dismissLockedTooltips();
|
||||||
|
Hooks.callAll(CONFIG.DH.HOOKS.hooksConfig.lockedTooltipDismissed);
|
||||||
|
}
|
||||||
|
|
||||||
/** Get HTML for Battlepoints tooltip */
|
/** Get HTML for Battlepoints tooltip */
|
||||||
async getBattlepointHTML(combatId) {
|
async getBattlepointHTML(combatId) {
|
||||||
const combat = game.combats.get(combatId);
|
const combat = game.combats.get(combatId);
|
||||||
|
|
|
||||||
|
|
@ -49,9 +49,7 @@ export default class RegisterHandlebarsHelpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
static damageSymbols(damageParts) {
|
static damageSymbols(damageParts) {
|
||||||
const symbols = [...new Set(damageParts.reduce((a, c) => a.concat([...c.type]), []))].map(
|
const symbols = [...new Set(damageParts.map(x => x.type))].map(p => CONFIG.DH.GENERAL.damageTypes[p].icon);
|
||||||
p => CONFIG.DH.GENERAL.damageTypes[p].icon
|
|
||||||
);
|
|
||||||
return new Handlebars.SafeString(Array.from(symbols).map(symbol => `<i class="fa-solid ${symbol}"></i>`));
|
return new Handlebars.SafeString(Array.from(symbols).map(symbol => `<i class="fa-solid ${symbol}"></i>`));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,13 @@ export const getCommandTarget = (options = {}) => {
|
||||||
|
|
||||||
export const setDiceSoNiceForDualityRoll = async (rollResult, advantageState, hopeFaces, fearFaces, advantageFaces) => {
|
export const setDiceSoNiceForDualityRoll = async (rollResult, advantageState, hopeFaces, fearFaces, advantageFaces) => {
|
||||||
if (!game.modules.get('dice-so-nice')?.active) return;
|
if (!game.modules.get('dice-so-nice')?.active) return;
|
||||||
const diceSoNicePresets = await getDiceSoNicePresets(hopeFaces, fearFaces, advantageFaces, advantageFaces);
|
const diceSoNicePresets = await getDiceSoNicePresets(
|
||||||
|
rollResult,
|
||||||
|
hopeFaces,
|
||||||
|
fearFaces,
|
||||||
|
advantageFaces,
|
||||||
|
advantageFaces
|
||||||
|
);
|
||||||
rollResult.dice[0].options = diceSoNicePresets.hope;
|
rollResult.dice[0].options = diceSoNicePresets.hope;
|
||||||
rollResult.dice[1].options = diceSoNicePresets.fear;
|
rollResult.dice[1].options = diceSoNicePresets.fear;
|
||||||
if (rollResult.dice[2] && advantageState) {
|
if (rollResult.dice[2] && advantageState) {
|
||||||
|
|
@ -378,21 +384,18 @@ export const arraysEqual = (a, b) =>
|
||||||
|
|
||||||
export const setsEqual = (a, b) => a.size === b.size && [...a].every(value => b.has(value));
|
export const setsEqual = (a, b) => a.size === b.size && [...a].every(value => b.has(value));
|
||||||
|
|
||||||
export function getResourceScrollTextData(resources, resource, key) {
|
export function getScrollTextData(actor, resource, key) {
|
||||||
const increased = resources[key].value < resource.value;
|
|
||||||
const value = -1 * (resources[key].value - resource.value);
|
|
||||||
|
|
||||||
return getScrollTextData(increased, value, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getScrollTextData(increased, value, key) {
|
|
||||||
const { reversed, label } = CONFIG.DH.ACTOR.scrollingTextResource[key];
|
|
||||||
const { BOTTOM, TOP } = CONST.TEXT_ANCHOR_POINTS;
|
const { BOTTOM, TOP } = CONST.TEXT_ANCHOR_POINTS;
|
||||||
|
|
||||||
|
const resources = actor.system.resources;
|
||||||
|
const increased = resources[key].value < resource.value;
|
||||||
|
const value = -1 * (resources[key].value - resource.value);
|
||||||
|
const { label, isReversed } = resources[key];
|
||||||
|
|
||||||
const text = `${game.i18n.localize(label)} ${value.signedString()}`;
|
const text = `${game.i18n.localize(label)} ${value.signedString()}`;
|
||||||
const stroke = increased ? (reversed ? 0xffffff : 0x000000) : reversed ? 0x000000 : 0xffffff;
|
const stroke = increased ? (isReversed ? 0xffffff : 0x000000) : isReversed ? 0x000000 : 0xffffff;
|
||||||
const fill = increased ? (reversed ? 0x0032b1 : 0xffe760) : reversed ? 0xffe760 : 0x0032b1;
|
const fill = increased ? (isReversed ? 0x0032b1 : 0xffe760) : isReversed ? 0xffe760 : 0x0032b1;
|
||||||
const direction = increased ? (reversed ? BOTTOM : TOP) : reversed ? TOP : BOTTOM;
|
const direction = increased ? (isReversed ? BOTTOM : TOP) : isReversed ? TOP : BOTTOM;
|
||||||
|
|
||||||
return { text, stroke, fill, direction };
|
return { text, stroke, fill, direction };
|
||||||
}
|
}
|
||||||
|
|
@ -726,3 +729,16 @@ export async function RefreshFeatures(
|
||||||
|
|
||||||
return refreshedActors;
|
return refreshedActors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getUnusedDamageTypes(parts) {
|
||||||
|
const usedKeys = Object.keys(parts);
|
||||||
|
return Object.keys(CONFIG.DH.GENERAL.healingTypes).reduce((acc, key) => {
|
||||||
|
if (!usedKeys.includes(key))
|
||||||
|
acc.push({
|
||||||
|
value: key,
|
||||||
|
label: game.i18n.localize(CONFIG.DH.GENERAL.healingTypes[key].label)
|
||||||
|
});
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,10 @@ export const preloadHandlebarsTemplates = async function () {
|
||||||
'systems/daggerheart/templates/sheets/global/partials/resource-section/dice-value.hbs',
|
'systems/daggerheart/templates/sheets/global/partials/resource-section/dice-value.hbs',
|
||||||
'systems/daggerheart/templates/sheets/global/partials/resource-section/die.hbs',
|
'systems/daggerheart/templates/sheets/global/partials/resource-section/die.hbs',
|
||||||
'systems/daggerheart/templates/sheets/global/partials/resource-bar.hbs',
|
'systems/daggerheart/templates/sheets/global/partials/resource-bar.hbs',
|
||||||
|
'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs',
|
||||||
|
'systems/daggerheart/templates/sheets/global/partials/item-tags.hbs',
|
||||||
'systems/daggerheart/templates/components/card-preview.hbs',
|
'systems/daggerheart/templates/components/card-preview.hbs',
|
||||||
'systems/daggerheart/templates/levelup/parts/selectable-card-preview.hbs',
|
'systems/daggerheart/templates/levelup/parts/selectable-card-preview.hbs',
|
||||||
'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs',
|
|
||||||
'systems/daggerheart/templates/ui/combatTracker/combatTrackerSection.hbs',
|
'systems/daggerheart/templates/ui/combatTracker/combatTrackerSection.hbs',
|
||||||
'systems/daggerheart/templates/actionTypes/damage.hbs',
|
'systems/daggerheart/templates/actionTypes/damage.hbs',
|
||||||
'systems/daggerheart/templates/actionTypes/resource.hbs',
|
'systems/daggerheart/templates/actionTypes/resource.hbs',
|
||||||
|
|
@ -33,6 +34,7 @@ export const preloadHandlebarsTemplates = async function () {
|
||||||
'systems/daggerheart/templates/actionTypes/beastform.hbs',
|
'systems/daggerheart/templates/actionTypes/beastform.hbs',
|
||||||
'systems/daggerheart/templates/actionTypes/countdown.hbs',
|
'systems/daggerheart/templates/actionTypes/countdown.hbs',
|
||||||
'systems/daggerheart/templates/actionTypes/summon.hbs',
|
'systems/daggerheart/templates/actionTypes/summon.hbs',
|
||||||
|
'systems/daggerheart/templates/actionTypes/transform.hbs',
|
||||||
'systems/daggerheart/templates/settings/components/settings-item-line.hbs',
|
'systems/daggerheart/templates/settings/components/settings-item-line.hbs',
|
||||||
'systems/daggerheart/templates/ui/tooltip/parts/tooltipChips.hbs',
|
'systems/daggerheart/templates/ui/tooltip/parts/tooltipChips.hbs',
|
||||||
'systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs',
|
'systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs',
|
||||||
|
|
@ -44,6 +46,7 @@ export const preloadHandlebarsTemplates = async function () {
|
||||||
'systems/daggerheart/templates/ui/chat/parts/target-part.hbs',
|
'systems/daggerheart/templates/ui/chat/parts/target-part.hbs',
|
||||||
'systems/daggerheart/templates/ui/chat/parts/button-part.hbs',
|
'systems/daggerheart/templates/ui/chat/parts/button-part.hbs',
|
||||||
'systems/daggerheart/templates/ui/itemBrowser/itemContainer.hbs',
|
'systems/daggerheart/templates/ui/itemBrowser/itemContainer.hbs',
|
||||||
'systems/daggerheart/templates/scene/dh-config.hbs'
|
'systems/daggerheart/templates/scene/dh-config.hbs',
|
||||||
|
'systems/daggerheart/templates/settings/appearance-settings/diceSoNiceTab.hbs'
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,18 @@
|
||||||
import { defaultLevelTiers, DhLevelTiers } from '../data/levelTier.mjs';
|
import { defaultLevelTiers, DhLevelTiers } from '../data/levelTier.mjs';
|
||||||
import DhCountdowns from '../data/countdowns.mjs';
|
import DhCountdowns from '../data/countdowns.mjs';
|
||||||
import { DhAppearance, DhAutomation, DhHomebrew, DhVariantRules } from '../data/settings/_module.mjs';
|
import {
|
||||||
|
DhAppearance,
|
||||||
|
DhAutomation,
|
||||||
|
DhGlobalOverrides,
|
||||||
|
DhHomebrew,
|
||||||
|
DhMetagaming,
|
||||||
|
DhVariantRules
|
||||||
|
} from '../data/settings/_module.mjs';
|
||||||
import {
|
import {
|
||||||
DhAppearanceSettings,
|
DhAppearanceSettings,
|
||||||
DhAutomationSettings,
|
DhAutomationSettings,
|
||||||
DhHomebrewSettings,
|
DhHomebrewSettings,
|
||||||
|
DhMetagamingSettings,
|
||||||
DhVariantRuleSettings
|
DhVariantRuleSettings
|
||||||
} from '../applications/settings/_module.mjs';
|
} from '../applications/settings/_module.mjs';
|
||||||
import { CompendiumBrowserSettings, DhTagTeamRoll } from '../data/_module.mjs';
|
import { CompendiumBrowserSettings, DhTagTeamRoll } from '../data/_module.mjs';
|
||||||
|
|
@ -38,18 +46,25 @@ const registerMenuSettings = () => {
|
||||||
type: DhAutomation
|
type: DhAutomation
|
||||||
});
|
});
|
||||||
|
|
||||||
|
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Metagaming, {
|
||||||
|
scope: 'world',
|
||||||
|
config: false,
|
||||||
|
type: DhMetagaming
|
||||||
|
});
|
||||||
|
|
||||||
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, {
|
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, {
|
||||||
scope: 'world',
|
scope: 'world',
|
||||||
config: false,
|
config: false,
|
||||||
type: DhHomebrew,
|
type: DhHomebrew,
|
||||||
onChange: value => {
|
onChange: value => {
|
||||||
if (value.maxFear) {
|
value.handleChange();
|
||||||
if (ui.resources) ui.resources.render({ force: true });
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Some homebrew settings may change sheets in various ways, so trigger a re-render
|
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.GlobalOverrides, {
|
||||||
resetActors();
|
scope: 'world',
|
||||||
}
|
config: false,
|
||||||
|
type: DhGlobalOverrides
|
||||||
});
|
});
|
||||||
|
|
||||||
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance, {
|
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance, {
|
||||||
|
|
@ -57,12 +72,7 @@ const registerMenuSettings = () => {
|
||||||
config: false,
|
config: false,
|
||||||
type: DhAppearance,
|
type: DhAppearance,
|
||||||
onChange: value => {
|
onChange: value => {
|
||||||
if (value.displayFear) {
|
value.handleChange();
|
||||||
if (ui.resources) {
|
|
||||||
if (value.displayFear === 'hide') ui.resources.close({ allowed: true });
|
|
||||||
else ui.resources.render({ force: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -76,6 +86,16 @@ const registerMenus = () => {
|
||||||
type: DhAutomationSettings,
|
type: DhAutomationSettings,
|
||||||
restricted: true
|
restricted: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
game.settings.registerMenu(CONFIG.DH.id, CONFIG.DH.SETTINGS.menu.Metagaming.Name, {
|
||||||
|
name: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.metagaming.name'),
|
||||||
|
label: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.metagaming.label'),
|
||||||
|
hint: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.metagaming.hint'),
|
||||||
|
icon: CONFIG.DH.SETTINGS.menu.Metagaming.Icon,
|
||||||
|
type: DhMetagamingSettings,
|
||||||
|
restricted: true
|
||||||
|
});
|
||||||
|
|
||||||
game.settings.registerMenu(CONFIG.DH.id, CONFIG.DH.SETTINGS.menu.Homebrew.Name, {
|
game.settings.registerMenu(CONFIG.DH.id, CONFIG.DH.SETTINGS.menu.Homebrew.Name, {
|
||||||
name: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.homebrew.name'),
|
name: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.homebrew.name'),
|
||||||
label: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.homebrew.label'),
|
label: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.homebrew.label'),
|
||||||
|
|
@ -144,30 +164,8 @@ const registerNonConfigSettings = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings, {
|
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings, {
|
||||||
scope: 'client',
|
scope: 'world',
|
||||||
config: false,
|
config: false,
|
||||||
type: CompendiumBrowserSettings
|
type: CompendiumBrowserSettings
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggers a reset and non-forced re-render on all given actors (if given)
|
|
||||||
* or all world actors and actors in all scenes to show immediate results for a changed setting.
|
|
||||||
*/
|
|
||||||
function resetActors(actors) {
|
|
||||||
actors ??= [
|
|
||||||
game.actors.contents,
|
|
||||||
game.scenes.contents.flatMap(s => s.tokens.contents).flatMap(t => t.actor ?? [])
|
|
||||||
].flat();
|
|
||||||
actors = new Set(actors);
|
|
||||||
for (const actor of actors) {
|
|
||||||
for (const app of Object.values(actor.apps)) {
|
|
||||||
for (const element of app.element?.querySelectorAll('prose-mirror.active')) {
|
|
||||||
element.open = false; // This triggers a save
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
actor.reset();
|
|
||||||
actor.render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -91,8 +91,8 @@
|
||||||
"useDefault": false
|
"useDefault": false
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -118,7 +118,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"_id": "TCKVaVweyJzhEArX",
|
"_id": "TCKVaVweyJzhEArX",
|
||||||
|
|
@ -343,7 +343,7 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [],
|
"parts": {},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -471,8 +471,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -499,7 +499,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
"armor": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -524,7 +524,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -598,8 +598,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -626,7 +626,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -652,8 +652,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -680,7 +680,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -75,8 +75,8 @@
|
||||||
},
|
},
|
||||||
"range": "veryClose",
|
"range": "veryClose",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -102,7 +102,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"chatDisplay": false
|
"chatDisplay": false
|
||||||
|
|
@ -400,8 +400,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -427,7 +427,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false,
|
"includeBase": false,
|
||||||
"direct": true
|
"direct": true
|
||||||
},
|
},
|
||||||
|
|
@ -508,7 +508,7 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [],
|
"parts": {},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -581,8 +581,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -608,7 +608,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
"hope": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -633,7 +633,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -72,8 +72,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -100,7 +100,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"img": "icons/weapons/daggers/dagger-bone-black.webp",
|
"img": "icons/weapons/daggers/dagger-bone-black.webp",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
|
||||||
|
|
@ -85,8 +85,8 @@
|
||||||
},
|
},
|
||||||
"range": "far",
|
"range": "far",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -112,7 +112,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"img": "icons/magic/unholy/beam-ringed-impact-purple.webp",
|
"img": "icons/magic/unholy/beam-ringed-impact-purple.webp",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -256,7 +256,7 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [],
|
"parts": {},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -336,8 +336,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -363,7 +363,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -414,8 +414,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"fear": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -440,7 +440,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -619,7 +619,7 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [],
|
"parts": {},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -692,8 +692,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -719,7 +719,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -107,7 +107,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"img": "icons/weapons/bows/longbow-recurve-leather-brown.webp",
|
"img": "icons/weapons/bows/longbow-recurve-leather-brown.webp",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -246,8 +246,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -273,7 +273,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,8 @@
|
||||||
"description": "<p>A group of trained archers bearing massive bows.</p>",
|
"description": "<p>A group of trained archers bearing massive bows.</p>",
|
||||||
"attack": {
|
"attack": {
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -95,7 +95,7 @@
|
||||||
"resultBased": false,
|
"resultBased": false,
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"name": "Longbow",
|
"name": "Longbow",
|
||||||
"img": "icons/weapons/bows/longbow-recurve-leather-brown.webp",
|
"img": "icons/weapons/bows/longbow-recurve-leather-brown.webp",
|
||||||
|
|
@ -270,8 +270,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -295,7 +295,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -368,8 +368,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -393,7 +393,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@
|
||||||
},
|
},
|
||||||
"range": "close",
|
"range": "close",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -108,7 +108,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"chatDisplay": false
|
"chatDisplay": false
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -107,7 +107,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"range": "melee",
|
"range": "melee",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -309,7 +309,7 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [],
|
"parts": {},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -382,8 +382,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -409,7 +409,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -482,8 +482,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -509,7 +509,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -582,8 +582,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -609,7 +609,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -737,8 +737,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -763,7 +763,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -836,7 +836,7 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [],
|
"parts": {},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -964,8 +964,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -991,7 +991,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -1071,8 +1071,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"fear": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -1097,7 +1097,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -1165,8 +1165,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -1192,7 +1192,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -111,7 +111,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"img": "icons/creatures/claws/claw-straight-brown.webp",
|
"img": "icons/creatures/claws/claw-straight-brown.webp",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -284,8 +284,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -311,7 +311,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -441,8 +441,8 @@
|
||||||
"consumeOnSuccess": false
|
"consumeOnSuccess": false
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"fear": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -468,7 +468,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,8 @@
|
||||||
"name": "Longsword",
|
"name": "Longsword",
|
||||||
"img": "icons/weapons/swords/sword-guard.webp",
|
"img": "icons/weapons/swords/sword-guard.webp",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -107,7 +107,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"range": "melee",
|
"range": "melee",
|
||||||
|
|
@ -246,7 +246,7 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [],
|
"parts": {},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -319,7 +319,7 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [],
|
"parts": {},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -83,8 +83,8 @@
|
||||||
},
|
},
|
||||||
"range": "veryClose",
|
"range": "veryClose",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"img": "icons/skills/melee/unarmed-punch-fist-yellow-red.webp",
|
"img": "icons/skills/melee/unarmed-punch-fist-yellow-red.webp",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -280,8 +280,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -307,7 +307,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false,
|
"includeBase": false,
|
||||||
"direct": true
|
"direct": true
|
||||||
},
|
},
|
||||||
|
|
@ -389,8 +389,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -415,7 +415,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,8 @@
|
||||||
},
|
},
|
||||||
"range": "veryClose",
|
"range": "veryClose",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"direct": true
|
"direct": true
|
||||||
},
|
},
|
||||||
"name": "Club",
|
"name": "Club",
|
||||||
|
|
@ -336,8 +336,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
|
|
@ -365,7 +365,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false,
|
"includeBase": false,
|
||||||
"direct": true
|
"direct": true
|
||||||
},
|
},
|
||||||
|
|
@ -412,8 +412,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"fear": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -438,7 +438,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -507,8 +507,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -534,7 +534,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false,
|
"includeBase": false,
|
||||||
"direct": true
|
"direct": true
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,8 @@
|
||||||
},
|
},
|
||||||
"range": "close",
|
"range": "close",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -101,7 +101,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"img": "icons/magic/light/beam-rays-magenta.webp",
|
"img": "icons/magic/light/beam-rays-magenta.webp",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -383,8 +383,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -410,7 +410,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -483,8 +483,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -508,7 +508,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -95,7 +95,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"chatDisplay": false
|
"chatDisplay": false
|
||||||
|
|
|
||||||
|
|
@ -72,8 +72,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -99,7 +99,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"name": "Fist Slam",
|
"name": "Fist Slam",
|
||||||
"img": "icons/skills/melee/unarmed-punch-fist-yellow-red.webp",
|
"img": "icons/skills/melee/unarmed-punch-fist-yellow-red.webp",
|
||||||
|
|
@ -332,8 +332,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -359,7 +359,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -534,8 +534,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -561,7 +561,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -111,7 +111,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"img": "icons/weapons/daggers/dagger-straight-cracked.webp",
|
"img": "icons/weapons/daggers/dagger-straight-cracked.webp",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -256,8 +256,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -282,7 +282,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"img": "icons/weapons/daggers/dagger-twin-green.webp",
|
"img": "icons/weapons/daggers/dagger-twin-green.webp",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -253,8 +253,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -279,7 +279,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -111,7 +111,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"range": "far",
|
"range": "far",
|
||||||
"img": "icons/weapons/staves/staff-ornate-purple.webp",
|
"img": "icons/weapons/staves/staff-ornate-purple.webp",
|
||||||
|
|
@ -256,8 +256,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -283,7 +283,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -308,7 +308,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -614,8 +614,8 @@
|
||||||
"recovery": "scene"
|
"recovery": "scene"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -640,7 +640,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -101,7 +101,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"range": "melee",
|
"range": "melee",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -300,8 +300,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -326,7 +326,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"range": "melee",
|
"range": "melee",
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"img": "icons/magic/nature/root-vines-grow-brown.webp",
|
"img": "icons/magic/nature/root-vines-grow-brown.webp",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -245,8 +245,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -271,7 +271,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -325,8 +325,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -350,7 +350,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -107,7 +107,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"range": "melee",
|
"range": "melee",
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -107,7 +107,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"range": "far",
|
"range": "far",
|
||||||
|
|
@ -435,8 +435,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hope": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -461,7 +461,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -515,8 +515,8 @@
|
||||||
"consumeOnSuccess": false
|
"consumeOnSuccess": false
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"fear": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -542,7 +542,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -108,7 +108,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"chatDisplay": false
|
"chatDisplay": false
|
||||||
|
|
@ -251,8 +251,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hope": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -277,7 +277,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -329,8 +329,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -355,7 +355,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -414,8 +414,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -441,7 +441,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -550,8 +550,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -576,7 +576,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,8 @@
|
||||||
},
|
},
|
||||||
"range": "far",
|
"range": "far",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -107,7 +107,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"direct": true
|
"direct": true
|
||||||
},
|
},
|
||||||
"img": "icons/magic/symbols/rune-sigil-rough-white-teal.webp",
|
"img": "icons/magic/symbols/rune-sigil-rough-white-teal.webp",
|
||||||
|
|
@ -352,7 +352,7 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [],
|
"parts": {},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@
|
||||||
},
|
},
|
||||||
"img": "icons/skills/melee/unarmed-punch-fist-yellow-red.webp",
|
"img": "icons/skills/melee/unarmed-punch-fist-yellow-red.webp",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -108,7 +108,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"direct": true
|
"direct": true
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -398,8 +398,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -425,7 +425,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false,
|
"includeBase": false,
|
||||||
"direct": true
|
"direct": true
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,8 @@
|
||||||
"motivesAndTactics": "Cause fear, consume fl esh, please masters",
|
"motivesAndTactics": "Cause fear, consume fl esh, please masters",
|
||||||
"attack": {
|
"attack": {
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -101,7 +101,7 @@
|
||||||
"resultBased": false,
|
"resultBased": false,
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"name": "Claws and Fangs",
|
"name": "Claws and Fangs",
|
||||||
"img": "icons/creatures/abilities/mouth-teeth-rows-red.webp",
|
"img": "icons/creatures/abilities/mouth-teeth-rows-red.webp",
|
||||||
|
|
@ -269,8 +269,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hope": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -295,7 +295,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -349,8 +349,8 @@
|
||||||
"consumeOnSuccess": false
|
"consumeOnSuccess": false
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"fear": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -376,7 +376,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -78,8 +78,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -105,7 +105,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"img": "icons/creatures/claws/claw-hooked-curved.webp",
|
"img": "icons/creatures/claws/claw-hooked-curved.webp",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -312,8 +312,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -337,7 +337,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -397,8 +397,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -424,7 +424,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"img": "icons/creatures/claws/claw-straight-brown.webp",
|
"img": "icons/creatures/claws/claw-straight-brown.webp",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -247,8 +247,8 @@
|
||||||
"consumeOnSuccess": false
|
"consumeOnSuccess": false
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -272,7 +272,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -352,8 +352,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -377,7 +377,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false,
|
"includeBase": false,
|
||||||
"direct": true
|
"direct": true
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@
|
||||||
},
|
},
|
||||||
"range": "far",
|
"range": "far",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -108,7 +108,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"chatDisplay": false
|
"chatDisplay": false
|
||||||
|
|
@ -251,7 +251,7 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [],
|
"parts": {},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -297,8 +297,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -324,7 +324,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -438,8 +438,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -464,7 +464,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
},
|
},
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -489,7 +489,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,8 @@
|
||||||
"motivesAndTactics": "Avoid larger predators, shock prey, tear apart",
|
"motivesAndTactics": "Avoid larger predators, shock prey, tear apart",
|
||||||
"attack": {
|
"attack": {
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -95,7 +95,7 @@
|
||||||
"resultBased": false,
|
"resultBased": false,
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"name": "Shocking Bite",
|
"name": "Shocking Bite",
|
||||||
"img": "icons/creatures/abilities/mouth-teeth-sharp.webp",
|
"img": "icons/creatures/abilities/mouth-teeth-sharp.webp",
|
||||||
|
|
@ -270,8 +270,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -297,7 +297,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,8 @@
|
||||||
},
|
},
|
||||||
"range": "close",
|
"range": "close",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -95,7 +95,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"chatDisplay": false
|
"chatDisplay": false
|
||||||
|
|
|
||||||
|
|
@ -98,8 +98,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -125,7 +125,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -276,8 +276,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -303,7 +303,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,8 @@
|
||||||
"type": "attack"
|
"type": "attack"
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"img": "icons/creatures/claws/claw-hooked-barbed.webp",
|
"img": "icons/creatures/claws/claw-hooked-barbed.webp",
|
||||||
"range": "melee",
|
"range": "melee",
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,8 @@
|
||||||
"img": "icons/weapons/axes/axe-battle-skull-black.webp",
|
"img": "icons/weapons/axes/axe-battle-skull-black.webp",
|
||||||
"range": "veryClose",
|
"range": "veryClose",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -95,7 +95,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"chatDisplay": false
|
"chatDisplay": false
|
||||||
|
|
@ -256,8 +256,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hope": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -282,7 +282,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,8 @@
|
||||||
},
|
},
|
||||||
"range": "far",
|
"range": "far",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -107,7 +107,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"img": "icons/weapons/staves/staff-animal-skull-bull.webp",
|
"img": "icons/weapons/staves/staff-animal-skull-bull.webp",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
|
|
@ -251,8 +251,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -278,7 +278,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -482,8 +482,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"stress": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -508,7 +508,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,8 @@
|
||||||
"useDefault": false
|
"useDefault": false
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"description": "",
|
"description": "",
|
||||||
|
|
@ -337,7 +337,7 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [],
|
"parts": {},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -416,8 +416,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -443,7 +443,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -516,8 +516,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -543,7 +543,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -653,8 +653,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hope": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -679,7 +679,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -717,7 +717,35 @@
|
||||||
"system": {
|
"system": {
|
||||||
"description": "<p>When the @Lookup[@name] marks their last HP, replace them with the @UUID[Compendium.daggerheart.adversaries.Actor.RXkZTwBRi4dJ3JE5]{Fallen Warlord: Undefeated Champion} and immediately spotlight them.</p>",
|
"description": "<p>When the @Lookup[@name] marks their last HP, replace them with the @UUID[Compendium.daggerheart.adversaries.Actor.RXkZTwBRi4dJ3JE5]{Fallen Warlord: Undefeated Champion} and immediately spotlight them.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {},
|
"actions": {
|
||||||
|
"gP426WmWbtrZEWCD": {
|
||||||
|
"type": "transform",
|
||||||
|
"_id": "gP426WmWbtrZEWCD",
|
||||||
|
"systemPath": "actions",
|
||||||
|
"baseAction": false,
|
||||||
|
"description": "",
|
||||||
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
|
"actionType": "action",
|
||||||
|
"triggers": [],
|
||||||
|
"cost": [],
|
||||||
|
"uses": {
|
||||||
|
"value": null,
|
||||||
|
"max": null,
|
||||||
|
"recovery": null,
|
||||||
|
"consumeOnSuccess": false
|
||||||
|
},
|
||||||
|
"transform": {
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.RXkZTwBRi4dJ3JE5",
|
||||||
|
"resourceRefresh": {
|
||||||
|
"hitPoints": true,
|
||||||
|
"stress": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"originItemType": null,
|
"originItemType": null,
|
||||||
"originId": null,
|
"originId": null,
|
||||||
"featureForm": "reaction"
|
"featureForm": "reaction"
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,8 @@
|
||||||
"useDefault": false
|
"useDefault": false
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"description": "",
|
"description": "",
|
||||||
|
|
@ -338,7 +338,7 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [],
|
"parts": {},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -410,8 +410,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -437,7 +437,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -697,8 +697,8 @@
|
||||||
"consumeOnSuccess": false
|
"consumeOnSuccess": false
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"fear": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -724,7 +724,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -792,8 +792,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hope": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -818,7 +818,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@
|
||||||
},
|
},
|
||||||
"range": "far",
|
"range": "far",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -108,7 +108,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"chatDisplay": false
|
"chatDisplay": false
|
||||||
|
|
@ -269,8 +269,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -294,7 +294,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@
|
||||||
},
|
},
|
||||||
"range": "veryClose",
|
"range": "veryClose",
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -108,7 +108,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"chatDisplay": false
|
"chatDisplay": false
|
||||||
|
|
@ -251,8 +251,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -278,7 +278,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -351,8 +351,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -378,7 +378,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -452,8 +452,8 @@
|
||||||
"consumeOnSuccess": false
|
"consumeOnSuccess": false
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"fear": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
@ -479,7 +479,7 @@
|
||||||
},
|
},
|
||||||
"type": []
|
"type": []
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -98,8 +98,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -125,7 +125,7 @@
|
||||||
},
|
},
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -345,8 +345,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -372,7 +372,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -499,8 +499,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -526,7 +526,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
@ -643,8 +643,8 @@
|
||||||
"recovery": null
|
"recovery": null
|
||||||
},
|
},
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -670,7 +670,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"includeBase": false
|
"includeBase": false
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,8 @@
|
||||||
"motivesAndTactics": "Fly away, harass, steal blood",
|
"motivesAndTactics": "Fly away, harass, steal blood",
|
||||||
"attack": {
|
"attack": {
|
||||||
"damage": {
|
"damage": {
|
||||||
"parts": [
|
"parts": {
|
||||||
{
|
"hitPoints": {
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
|
@ -101,7 +101,7 @@
|
||||||
"resultBased": false,
|
"resultBased": false,
|
||||||
"base": false
|
"base": false
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"name": "Proboscis",
|
"name": "Proboscis",
|
||||||
"img": "icons/skills/wounds/blood-cells-vessel-red.webp",
|
"img": "icons/skills/wounds/blood-cells-vessel-red.webp",
|
||||||
|
|
|
||||||
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