mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-04-23 07:53:39 +02:00
Merged with v14-Dev
This commit is contained in:
commit
88be00567e
650 changed files with 6323 additions and 4508 deletions
|
|
@ -554,7 +554,7 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
|
|||
experiences: {
|
||||
...this.setup.experiences,
|
||||
...Object.keys(this.character.system.experiences).reduce((acc, key) => {
|
||||
acc[`-=${key}`] = null;
|
||||
acc[`${key}`] = _del;
|
||||
return acc;
|
||||
}, {})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,8 +77,8 @@ export default class CharacterResetDialog extends HandlebarsApplicationMixin(App
|
|||
|
||||
if (!this.data.optional.portrait.keep) {
|
||||
foundry.utils.setProperty(update, 'img', this.actor.schema.fields.img.initial(this.actor));
|
||||
foundry.utils.setProperty(update, 'prototypeToken.==texture', {});
|
||||
foundry.utils.setProperty(update, 'prototypeToken.==ring', {});
|
||||
foundry.utils.setProperty(update, 'prototypeToken.texture', _replace({}));
|
||||
foundry.utils.setProperty(update, 'prototypeToken.ring', _replace({}));
|
||||
}
|
||||
|
||||
if (this.data.optional.biography.keep)
|
||||
|
|
@ -89,7 +89,7 @@ export default class CharacterResetDialog extends HandlebarsApplicationMixin(App
|
|||
const { system, ...rest } = update;
|
||||
await this.actor.update({
|
||||
...rest,
|
||||
'==system': system ?? {}
|
||||
system: _replace(system ?? {})
|
||||
});
|
||||
|
||||
const inventoryItemTypes = ['weapon', 'armor', 'consumable', 'loot'];
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { refreshIsAllowed } from '../../helpers/utils.mjs';
|
||||
import { expireActiveEffects, refreshIsAllowed } from '../../helpers/utils.mjs';
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
||||
|
|
@ -264,6 +264,8 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
|
|||
await feature.update({ 'system.resource.value': resetValue });
|
||||
}
|
||||
|
||||
expireActiveEffects(this.actor, [this.shortRest ? 'shortRest' : 'longRest']);
|
||||
|
||||
this.close();
|
||||
} else {
|
||||
this.render();
|
||||
|
|
|
|||
|
|
@ -245,19 +245,21 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
if (error) return error;
|
||||
|
||||
await this.party.update({
|
||||
'system.==tagTeam': new game.system.api.data.TagTeamData({
|
||||
...this.party.system.tagTeam.toObject(),
|
||||
initiator: this.initiator,
|
||||
members: this.partyMembers.reduce((acc, member) => {
|
||||
if (member.selected)
|
||||
acc[member.id] = {
|
||||
name: member.name,
|
||||
img: member.img,
|
||||
rollType: CONFIG.DH.GENERAL.tagTeamRollTypes.trait.id
|
||||
};
|
||||
return acc;
|
||||
}, {})
|
||||
})
|
||||
'system.tagTeam': _replace(
|
||||
new game.system.api.data.TagTeamData({
|
||||
...this.party.system.tagTeam.toObject(),
|
||||
initiator: this.initiator,
|
||||
members: this.partyMembers.reduce((acc, member) => {
|
||||
if (member.selected)
|
||||
acc[member.id] = {
|
||||
name: member.name,
|
||||
img: member.img,
|
||||
rollType: CONFIG.DH.GENERAL.tagTeamRollTypes.trait.id
|
||||
};
|
||||
return acc;
|
||||
}, {})
|
||||
})
|
||||
)
|
||||
});
|
||||
|
||||
const hookData = { openForAllPlayers: this.openForAllPlayers, partyId: this.party.id };
|
||||
|
|
@ -566,7 +568,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
return mainRoll;
|
||||
}
|
||||
|
||||
static async #onCancelRoll(options = { confirm: true }) {
|
||||
static async #onCancelRoll(_event, _button, options = { confirm: true }) {
|
||||
this.cancelRoll(options);
|
||||
}
|
||||
|
||||
|
|
@ -584,9 +586,9 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
|
||||
await this.updatePartyData(
|
||||
{
|
||||
'system.==tagTeam': {
|
||||
'system.tagTeam': {
|
||||
initiator: null,
|
||||
members: {}
|
||||
members: _replace({})
|
||||
}
|
||||
},
|
||||
{ render: false }
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ export default class DhCompanionLevelUp extends BaseLevelUp {
|
|||
break;
|
||||
case 'summary':
|
||||
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;
|
||||
|
||||
let achievementExperiences = [];
|
||||
|
|
|
|||
|
|
@ -477,7 +477,7 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
|||
const secondaryData = Object.keys(
|
||||
foundry.utils.getProperty(this.levelup, `${target.dataset.path}.secondaryData`)
|
||||
).reduce((acc, key) => {
|
||||
acc[`-=${key}`] = null;
|
||||
acc[key] = _del;
|
||||
return acc;
|
||||
}, {});
|
||||
await this.levelup.updateSource({
|
||||
|
|
@ -511,9 +511,9 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
|||
const current = foundry.utils.getProperty(this.levelup, `${basePath}.${button.dataset.option}`);
|
||||
if (Number(button.dataset.cost) > 1 || Object.keys(current).length === 1) {
|
||||
// Simple handling that doesn't cover potential Custom LevelTiers.
|
||||
update[`${basePath}.-=${button.dataset.option}`] = null;
|
||||
update[`${basePath}.${button.dataset.option}`] = _del;
|
||||
} else {
|
||||
update[`${basePath}.${button.dataset.option}.-=${button.dataset.checkboxNr}`] = null;
|
||||
update[`${basePath}.${button.dataset.option}.${button.dataset.checkboxNr}`] = _del;
|
||||
}
|
||||
} else {
|
||||
if (this.levelup.levels[this.levelup.currentLevel].nrSelections.available < Number(button.dataset.cost)) {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,15 @@ export default class DhSceneConfigSettings extends foundry.applications.sheets.S
|
|||
}
|
||||
|
||||
async _onDrop(event) {
|
||||
event.stopPropagation();
|
||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
||||
if (data.type === 'Level') {
|
||||
const level = await foundry.documents.Level.fromDropData(data);
|
||||
if (level?.parent === this.document) return this._onSortLevel(event, level);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const item = await foundry.utils.fromUuid(data.uuid);
|
||||
if (item instanceof game.system.api.documents.DhpActor && item.type === 'environment') {
|
||||
let sceneUuid = data.uuid;
|
||||
|
|
@ -114,7 +122,7 @@ export default class DhSceneConfigSettings extends foundry.applications.sheets.S
|
|||
|
||||
for (const key of Object.keys(this.document._source.flags.daggerheart?.sceneEnvironments ?? {})) {
|
||||
if (!submitData.flags.daggerheart.sceneEnvironments[key]) {
|
||||
submitData.flags.daggerheart.sceneEnvironments[`-=${key}`] = null;
|
||||
submitData.flags.daggerheart.sceneEnvironments[key] = _del;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
|||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
id: 'daggerheart-appearance-settings',
|
||||
classes: ['daggerheart', 'dialog', 'dh-style', 'setting'],
|
||||
classes: ['daggerheart', 'dialog', 'dh-style', 'setting', 'appearance-settings'],
|
||||
position: { width: '600', height: 'auto' },
|
||||
window: {
|
||||
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 */
|
||||
_configureRenderParts(options) {
|
||||
const parts = super._configureRenderParts(options);
|
||||
|
|
@ -83,15 +91,20 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
|||
/**@inheritdoc */
|
||||
async _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.globalOverrides = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.GlobalOverrides);
|
||||
}
|
||||
|
||||
context.setting = this.setting;
|
||||
context.globalOverrides = this.globalOverrides;
|
||||
context.fields = this.setting.schema.fields;
|
||||
|
||||
context.tabs = this._prepareTabs('general');
|
||||
context.dsnTabs = this._prepareTabs('diceSoNice');
|
||||
|
||||
context.isGM = game.user.isGM;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
@ -120,6 +133,9 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
|||
* @protected
|
||||
*/
|
||||
async prepareDiceSoNiceContext(context) {
|
||||
context.animationEvents = CONFIG.DH.GENERAL.daggerheartDiceAnimationEvents;
|
||||
context.previewAnimation = this.previewAnimation;
|
||||
|
||||
context.diceSoNiceTextures = Object.entries(game.dice3d.exports.TEXTURELIST).reduce(
|
||||
(acc, [k, v]) => ({
|
||||
...acc,
|
||||
|
|
@ -146,6 +162,13 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
|||
);
|
||||
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(
|
||||
context.dsnTabs,
|
||||
['hope', 'fear', 'advantage', 'disadvantage'].reduce(
|
||||
|
|
@ -153,7 +176,8 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
|||
...acc,
|
||||
[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
|
||||
* @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));
|
||||
|
||||
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.
|
||||
* @this {DHAppearanceSettings}
|
||||
|
|
@ -183,13 +214,25 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
|||
*/
|
||||
static async #onPreview(_, target) {
|
||||
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 faces = ['advantage', 'disadvantage'].includes(key) ? 'd6' : 'd12';
|
||||
const preset = await getDiceSoNicePreset(diceSoNice[key], faces);
|
||||
const diceSoNiceRoll = await new foundry.dice.Roll(`1${faces}`).evaluate();
|
||||
diceSoNiceRoll.dice[0].options.appearance = preset.appearance;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
const isDowntime = ['shortRest', 'longRest'].includes(type);
|
||||
const path = isDowntime ? `restMoves.${type}.moves` : `itemFeatures.${type}`;
|
||||
await this.settings.updateSource({
|
||||
[`${path}.-=${id}`]: null
|
||||
[`${path}.${id}`]: _del
|
||||
});
|
||||
|
||||
game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, this.settings.toObject());
|
||||
|
|
@ -322,7 +322,7 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
const fields = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).schema.fields;
|
||||
|
||||
const removeUpdate = Object.keys(this.settings.restMoves[target.dataset.type].moves).reduce((acc, key) => {
|
||||
acc[`-=${key}`] = null;
|
||||
acc[key] = _del;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
|
@ -382,7 +382,7 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
[`itemFeatures.${target.dataset.type}`]: Object.keys(
|
||||
this.settings.itemFeatures[target.dataset.type]
|
||||
).reduce((acc, key) => {
|
||||
acc[`-=${key}`] = null;
|
||||
acc[key] = _del;
|
||||
|
||||
return acc;
|
||||
}, {})
|
||||
|
|
@ -455,12 +455,12 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
if (!confirmed) return;
|
||||
|
||||
await this.settings.updateSource({
|
||||
[`domains.-=${this.selected.domain}`]: null
|
||||
[`domains.${this.selected.domain}`]: _del
|
||||
});
|
||||
|
||||
const currentSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew);
|
||||
if (currentSettings.domains[this.selected.domain]) {
|
||||
await currentSettings.updateSource({ [`domains.-=${this.selected.domain}`]: null });
|
||||
await currentSettings.updateSource({ [`domains.${this.selected.domain}`]: _del });
|
||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, currentSettings);
|
||||
}
|
||||
|
||||
|
|
@ -507,7 +507,7 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
|
||||
static async deleteAdversaryType(_, target) {
|
||||
const { key } = target.dataset;
|
||||
await this.settings.updateSource({ [`adversaryTypes.-=${key}`]: null });
|
||||
await this.settings.updateSource({ [`adversaryTypes.${key}`]: _del });
|
||||
|
||||
this.selected.adversaryType = this.selected.adversaryType === key ? null : this.selected.adversaryType;
|
||||
this.render();
|
||||
|
|
@ -563,7 +563,7 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
|
||||
const { actorType, resourceKey } = target.dataset;
|
||||
await this.settings.updateSource({
|
||||
[`resources.${actorType}.resources.-=${resourceKey}`]: null
|
||||
[`resources.${actorType}.resources.${resourceKey}`]: _del
|
||||
});
|
||||
|
||||
game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, this.settings.toObject());
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { getUnusedDamageTypes } from '../../helpers/utils.mjs';
|
||||
import DaggerheartSheet from '../sheets/daggerheart-sheet.mjs';
|
||||
|
||||
const { ApplicationV2 } = foundry.applications.api;
|
||||
|
|
@ -104,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) {
|
||||
for (const v of Object.values(tabs)) {
|
||||
|
|
@ -172,6 +173,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
|||
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;
|
||||
context.tierOptions = [
|
||||
|
|
@ -291,18 +293,61 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
|||
|
||||
static addDamage(_event) {
|
||||
if (!this.action.damage.parts) return;
|
||||
const data = this.action.toObject(),
|
||||
part = {};
|
||||
if (this.action.actor?.isNPC) part.value = { multiplier: 'flat' };
|
||||
data.damage.parts.push(part);
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
|
||||
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' };
|
||||
data.damage.parts[type] = part;
|
||||
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) {
|
||||
if (!this.action.damage.parts) return;
|
||||
const data = this.action.toObject(),
|
||||
index = button.dataset.index;
|
||||
data.damage.parts.splice(index, 1);
|
||||
const data = this.action.toObject();
|
||||
const key = button.dataset.key;
|
||||
delete data.damage.parts[key];
|
||||
data.damage.parts[`${key}`] = _del;
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac
|
|||
settings: { template: 'systems/daggerheart/templates/sheets/activeEffect/settings.hbs' },
|
||||
changes: {
|
||||
template: 'systems/daggerheart/templates/sheets/activeEffect/changes.hbs',
|
||||
templates: ['systems/daggerheart/templates/sheets/activeEffect/change.hbs'],
|
||||
scrollable: ['ol[data-changes]']
|
||||
},
|
||||
footer: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-form-footer.hbs' }
|
||||
|
|
@ -173,8 +174,77 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac
|
|||
}));
|
||||
}
|
||||
break;
|
||||
case 'settings':
|
||||
const groups = {
|
||||
time: _loc('EFFECT.DURATION.UNITS.GROUPS.time'),
|
||||
combat: _loc('EFFECT.DURATION.UNITS.GROUPS.combat')
|
||||
};
|
||||
partContext.durationUnits = CONST.ACTIVE_EFFECT_DURATION_UNITS.map(value => ({
|
||||
value,
|
||||
label: _loc(`EFFECT.DURATION.UNITS.${value}`),
|
||||
group: CONST.ACTIVE_EFFECT_TIME_DURATION_UNITS.includes(value) ? groups.time : groups.combat
|
||||
}));
|
||||
break;
|
||||
case 'changes':
|
||||
const fields = this.document.system.schema.fields.changes.element.fields;
|
||||
partContext.changes = await Promise.all(
|
||||
foundry.utils
|
||||
.deepClone(context.source.changes)
|
||||
.map((c, i) => this._prepareChangeContext(c, i, fields))
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return partContext;
|
||||
}
|
||||
|
||||
_prepareChangeContext(change, index, fields) {
|
||||
if (typeof change.value !== 'string') change.value = JSON.stringify(change.value);
|
||||
const defaultPriority = game.system.api.documents.DhActiveEffect.CHANGE_TYPES[change.type]?.defaultPriority;
|
||||
Object.assign(
|
||||
change,
|
||||
['key', 'type', 'value', 'priority'].reduce((paths, fieldName) => {
|
||||
paths[`${fieldName}Path`] = `system.changes.${index}.${fieldName}`;
|
||||
return paths;
|
||||
}, {})
|
||||
);
|
||||
return (
|
||||
game.system.api.documents.DhActiveEffect.CHANGE_TYPES[change.type].render?.(
|
||||
change,
|
||||
index,
|
||||
defaultPriority
|
||||
) ??
|
||||
foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/sheets/activeEffect/change.hbs',
|
||||
{
|
||||
change,
|
||||
index,
|
||||
defaultPriority,
|
||||
fields
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
_onChangeForm(_formConfig, event) {
|
||||
if (foundry.utils.isElementInstanceOf(event.target, 'select') && event.target.name === 'system.duration.type') {
|
||||
const durationSection = this.element.querySelector('.custom-duration-section');
|
||||
if (event.target.value === 'custom') durationSection.classList.add('visible');
|
||||
else durationSection.classList.remove('visible');
|
||||
|
||||
const durationDescription = this.element.querySelector('.duration-description');
|
||||
if (event.target.value === 'temporary') durationDescription.classList.add('visible');
|
||||
else durationDescription.classList.remove('visible');
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
_processFormData(event, form, formData) {
|
||||
const submitData = super._processFormData(event, form, formData);
|
||||
if (submitData.start && !submitData.start.time) submitData.start.time = '0';
|
||||
else if (!submitData) submitData.start = null;
|
||||
|
||||
return submitData;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
|
|||
});
|
||||
if (!confirmed) return;
|
||||
|
||||
await this.actor.update({ [`system.experiences.-=${target.dataset.experience}`]: null });
|
||||
await this.actor.update({ [`system.experiences.${target.dataset.experience}`]: _del });
|
||||
}
|
||||
|
||||
async _onDragStart(event) {
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@ export default class DHCharacterSettings extends DHBaseActorSettings {
|
|||
|
||||
if (relinkAchievementData.length > 0) {
|
||||
relinkAchievementData.forEach(data => {
|
||||
updates[`system.levelData.levelups.${data.levelKey}.achievements.experiences.-=${data.experience}`] =
|
||||
null;
|
||||
updates[`system.levelData.levelups.${data.levelKey}.achievements.experiences.${data.experience}`] =
|
||||
_del;
|
||||
});
|
||||
} else if (relinkSelectionData.length > 0) {
|
||||
relinkSelectionData.forEach(data => {
|
||||
|
|
@ -137,7 +137,7 @@ export default class DHCharacterSettings extends DHBaseActorSettings {
|
|||
|
||||
await this.actor.update({
|
||||
...updates,
|
||||
[`system.experiences.-=${target.dataset.experience}`]: null
|
||||
[`system.experiences.${target.dataset.experience}`]: _del
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,6 +117,6 @@ export default class DHCompanionSettings extends DHBaseActorSettings {
|
|||
});
|
||||
if (!confirmed) return;
|
||||
|
||||
await this.actor.update({ [`system.experiences.-=${target.dataset.experience}`]: null });
|
||||
await this.actor.update({ [`system.experiences.${target.dataset.experience}`]: _del });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,9 +68,9 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
|
|||
*/
|
||||
static async #addCategory() {
|
||||
await this.actor.update({
|
||||
[`system.potentialAdversaries.${foundry.utils.randomID()}.label`]: game.i18n.localize(
|
||||
'DAGGERHEART.ACTORS.Environment.newAdversary'
|
||||
)
|
||||
[`system.potentialAdversaries.${foundry.utils.randomID()}`]: {
|
||||
label: game.i18n.localize('DAGGERHEART.ACTORS.Environment.newAdversary')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
|
|||
* @type {ApplicationClickAction}
|
||||
*/
|
||||
static async #removeCategory(_, target) {
|
||||
await this.actor.update({ [`system.potentialAdversaries.-=${target.dataset.categoryId}`]: null });
|
||||
await this.actor.update({ [`system.potentialAdversaries.${target.dataset.categoryId}`]: _del });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -138,4 +138,8 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
|
|||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
async _onDropItem(event, item) {
|
||||
console.log(item);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ export default class SettingFeatureConfig extends HandlebarsApplicationMixin(App
|
|||
}
|
||||
});
|
||||
} else {
|
||||
await this.updateMove({ [`${this.actionsPath}.-=${target.dataset.id}`]: null });
|
||||
await this.updateMove({ [`${this.actionsPath}.${target.dataset.id}`]: _del });
|
||||
}
|
||||
|
||||
this.render();
|
||||
|
|
|
|||
|
|
@ -67,9 +67,9 @@ export default function DHTokenConfigMixin(Base) {
|
|||
changes.height = tokenSize;
|
||||
}
|
||||
|
||||
const deletions = { '-=actorId': null, '-=actorLink': null };
|
||||
const deletions = { actorId: _del, actorLink: _del };
|
||||
const mergeOptions = { inplace: false, performDeletions: true };
|
||||
this._preview.updateSource(mergeObject(changes, deletions, mergeOptions));
|
||||
this._preview.updateSource(foundry.utils.mergeObject(changes, deletions, mergeOptions));
|
||||
|
||||
if (this._preview?.object?.destroyed === false) {
|
||||
this._preview.object.initializeSources();
|
||||
|
|
|
|||
|
|
@ -72,19 +72,16 @@ const typeSettingsMap = {
|
|||
*/
|
||||
export default function DHApplicationMixin(Base) {
|
||||
class DHSheetV2 extends HandlebarsApplicationMixin(Base) {
|
||||
#nonHeaderAttribution = ['environment', 'ancestry', 'community', 'domainCard'];
|
||||
|
||||
/**
|
||||
* @param {DHSheetV2Configuration} [options={}]
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
super(options);
|
||||
/**
|
||||
* @type {foundry.applications.ux.DragDrop[]}
|
||||
* @private
|
||||
*/
|
||||
this._dragDrop = this._createDragDropHandlers();
|
||||
}
|
||||
|
||||
#nonHeaderAttribution = ['environment', 'ancestry', 'community', 'domainCard'];
|
||||
this._setupDragDrop();
|
||||
}
|
||||
|
||||
/**
|
||||
* The default options for the sheet.
|
||||
|
|
@ -177,7 +174,9 @@ export default function DHApplicationMixin(Base) {
|
|||
/**@inheritdoc */
|
||||
_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
|
||||
for (const deltaInput of htmlElement.querySelectorAll('input[data-allow-delta]')) {
|
||||
|
|
@ -355,14 +354,19 @@ export default function DHApplicationMixin(Base) {
|
|||
* @returns {foundry.applications.ux.DragDrop[]}
|
||||
* @private
|
||||
*/
|
||||
_createDragDropHandlers() {
|
||||
return 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);
|
||||
});
|
||||
_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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -499,7 +503,10 @@ export default function DHApplicationMixin(Base) {
|
|||
icon: 'fa-solid fa-explosion',
|
||||
condition: 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) => {
|
||||
const doc = await getDocFromElement(target),
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ export default class BeastformSheet extends DHBaseItemSheet {
|
|||
|
||||
async advantageOnRemove(event) {
|
||||
await this.document.update({
|
||||
[`system.advantageOn.-=${event.detail.data.value}`]: null
|
||||
[`system.advantageOn.${event.detail.data.value}`]: _del
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,14 +108,15 @@ export default class DhRollTableSheet extends foundry.applications.sheets.RollTa
|
|||
getSystemFlagUpdate() {
|
||||
const deleteUpdate = Object.keys(this.document._source.flags.daggerheart?.altFormula ?? {}).reduce(
|
||||
(acc, formulaKey) => {
|
||||
if (!this.daggerheartFlag.altFormula[formulaKey]) acc.altFormula[`-=${formulaKey}`] = null;
|
||||
if (!this.daggerheartFlag.altFormula[formulaKey]) acc.altFormula[formulaKey] = _del;
|
||||
|
||||
return acc;
|
||||
},
|
||||
{ altFormula: {} }
|
||||
);
|
||||
|
||||
return { ['flags.daggerheart']: foundry.utils.mergeObject(this.daggerheartFlag.toObject(), deleteUpdate) };
|
||||
const flagData = this.daggerheartFlag.toObject();
|
||||
return { ...flagData, altFormula: { ...flagData.altFormula, ...deleteUpdate.altFormula } };
|
||||
}
|
||||
|
||||
static async #addFormula() {
|
||||
|
|
@ -127,7 +128,7 @@ export default class DhRollTableSheet extends foundry.applications.sheets.RollTa
|
|||
|
||||
static async #removeFormula(_event, target) {
|
||||
await this.daggerheartFlag.updateSource({
|
||||
[`altFormula.-=${target.dataset.key}`]: null
|
||||
[`altFormula.${target.dataset.key}`]: _del
|
||||
});
|
||||
this.render({ internalRefresh: true });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,52 +1,19 @@
|
|||
export default class DhSidebar extends foundry.applications.sidebar.Sidebar {
|
||||
static buildTabs() {
|
||||
const { settings, ...tabs } = super.TABS;
|
||||
return {
|
||||
...tabs,
|
||||
daggerheartMenu: {
|
||||
tooltip: 'DAGGERHEART.UI.Sidebar.daggerheartMenu.title',
|
||||
img: 'systems/daggerheart/assets/logos/FoundryBorneLogoWhite.svg',
|
||||
gmOnly: true
|
||||
},
|
||||
settings
|
||||
};
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static TABS = {
|
||||
chat: {
|
||||
documentName: 'ChatMessage'
|
||||
},
|
||||
combat: {
|
||||
documentName: 'Combat'
|
||||
},
|
||||
scenes: {
|
||||
documentName: 'Scene',
|
||||
gmOnly: true
|
||||
},
|
||||
actors: {
|
||||
documentName: 'Actor'
|
||||
},
|
||||
items: {
|
||||
documentName: 'Item'
|
||||
},
|
||||
journal: {
|
||||
documentName: 'JournalEntry',
|
||||
tooltip: 'SIDEBAR.TabJournal'
|
||||
},
|
||||
tables: {
|
||||
documentName: 'RollTable'
|
||||
},
|
||||
cards: {
|
||||
documentName: 'Cards'
|
||||
},
|
||||
macros: {
|
||||
documentName: 'Macro'
|
||||
},
|
||||
playlists: {
|
||||
documentName: 'Playlist'
|
||||
},
|
||||
compendium: {
|
||||
tooltip: 'SIDEBAR.TabCompendium',
|
||||
icon: 'fa-solid fa-book-atlas'
|
||||
},
|
||||
daggerheartMenu: {
|
||||
tooltip: 'DAGGERHEART.UI.Sidebar.daggerheartMenu.title',
|
||||
img: 'systems/daggerheart/assets/logos/FoundryBorneLogoWhite.svg',
|
||||
gmOnly: true
|
||||
},
|
||||
settings: {
|
||||
tooltip: 'SIDEBAR.TabSettings',
|
||||
icon: 'fa-solid fa-gears'
|
||||
}
|
||||
};
|
||||
static TABS = DhSidebar.buildTabs();
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { AdversaryBPPerEncounter } from '../../config/encounterConfig.mjs';
|
||||
import { expireActiveEffects } from '../../helpers/utils.mjs';
|
||||
|
||||
export default class DhCombatTracker extends foundry.applications.sidebar.tabs.CombatTracker {
|
||||
static DEFAULT_OPTIONS = {
|
||||
|
|
@ -177,6 +178,8 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C
|
|||
if (autoPoints) {
|
||||
update.system.actionTokens = Math.max(combatant.system.actionTokens - 1, 0);
|
||||
}
|
||||
|
||||
if (combatant.actor) expireActiveEffects(combatant.actor, [CONFIG.DH.GENERAL.activeEffectDurations.act.id]);
|
||||
}
|
||||
|
||||
await this.viewed.update({
|
||||
|
|
|
|||
|
|
@ -233,6 +233,6 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio
|
|||
}
|
||||
|
||||
if (this.editingCountdowns.has(countdownId)) this.editingCountdowns.delete(countdownId);
|
||||
this.updateSetting({ [`countdowns.-=${countdownId}`]: null });
|
||||
this.updateSetting({ [`countdowns.${countdownId}`]: _del });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,10 +52,6 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
}
|
||||
};
|
||||
|
||||
get element() {
|
||||
return document.body.querySelector('.daggerheart.dh-style.countdowns');
|
||||
}
|
||||
|
||||
/**@inheritdoc */
|
||||
async _renderFrame(options) {
|
||||
const frame = await super._renderFrame(options);
|
||||
|
|
@ -68,6 +64,7 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
|
||||
const header = frame.querySelector('.window-header');
|
||||
header.querySelector('button[data-action="close"]').remove();
|
||||
header.querySelector('button[data-action="toggleControls"]').remove();
|
||||
|
||||
if (game.user.isGM) {
|
||||
const editTooltip = game.i18n.localize('DAGGERHEART.APPLICATIONS.CountdownEdit.editTitle');
|
||||
|
|
@ -278,10 +275,8 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
return acc;
|
||||
}, {})
|
||||
};
|
||||
await emitAsGM(GMUpdateEvent.UpdateCountdowns,
|
||||
DhCountdowns.gmSetSetting.bind(settings),
|
||||
settings, null, {
|
||||
refreshType: RefreshType.Countdown
|
||||
await emitAsGM(GMUpdateEvent.UpdateCountdowns, DhCountdowns.gmSetSetting.bind(settings), settings, null, {
|
||||
refreshType: RefreshType.Countdown
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { getIconVisibleActiveEffects } from '../../helpers/utils.mjs';
|
||||
import { RefreshType } from '../../systemRegistration/socket.mjs';
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
|
@ -72,7 +73,7 @@ export default class DhEffectsDisplay extends HandlebarsApplicationMixin(Applica
|
|||
? game.user.character
|
||||
: null
|
||||
: canvas.tokens.controlled[0].actor;
|
||||
return actor?.getActiveEffects() ?? [];
|
||||
return getIconVisibleActiveEffects(actor?.getActiveEffects() ?? []);
|
||||
};
|
||||
|
||||
toggleHidden(token, focused) {
|
||||
|
|
|
|||
|
|
@ -251,10 +251,10 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
|
||||
/* If any noticeable slowdown occurs, consider replacing with enriching description on clicking to expand descriptions */
|
||||
for (const item of this.items) {
|
||||
if (["weapon", "armor"].includes(item.type)) {
|
||||
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
|
||||
);
|
||||
}
|
||||
item.system.enrichedDescription =
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export default class DhSceneNavigation extends foundry.applications.ui.SceneNavi
|
|||
const environments = daggerheartInfo.sceneEnvironments.filter(
|
||||
x => x && x.testUserPermission(game.user, 'LIMITED')
|
||||
);
|
||||
const hasEnvironments = environments.length > 0 && x.isView;
|
||||
const hasEnvironments = environments.length > 0 && x.active;
|
||||
return {
|
||||
...x,
|
||||
hasEnvironments,
|
||||
|
|
@ -39,9 +39,10 @@ export default class DhSceneNavigation extends foundry.applications.ui.SceneNavi
|
|||
environments: environments
|
||||
};
|
||||
});
|
||||
|
||||
context.scenes.active = extendScenes(context.scenes.active);
|
||||
context.scenes.inactive = extendScenes(context.scenes.inactive);
|
||||
|
||||
context.scenes.viewed = context.scenes.viewed ? extendScenes([context.scenes.viewed])[0] : null;
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,46 +52,6 @@
|
|||
* @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?.callback(this.#jQuery ? $(this.target) : this.target, event);
|
||||
this.close();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Trigger a context menu event in response to a normal click on a additional options button.
|
||||
* @param {PointerEvent} event
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue