mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-03-10 19:17:09 +01:00
Compare commits
10 commits
2c36da8433
...
da368f3df5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da368f3df5 | ||
|
|
483caa1062 | ||
|
|
307af5b990 | ||
|
|
22d446f360 | ||
|
|
ae91d6786f | ||
|
|
cd52aa8f9c | ||
|
|
9553f3387f | ||
|
|
4c51bb5899 | ||
|
|
94efbeada3 | ||
|
|
1bc9e07098 |
40 changed files with 262 additions and 252 deletions
|
|
@ -2405,6 +2405,14 @@
|
|||
"hideAttribution": {
|
||||
"label": "Hide Attribution"
|
||||
},
|
||||
"showTokenDistance": {
|
||||
"label": "Show Token Distance on Hover",
|
||||
"choices": {
|
||||
"always": "Always",
|
||||
"encounters": "Encounters",
|
||||
"never": "Never"
|
||||
}
|
||||
},
|
||||
"expandedTitle": "Auto-expand Descriptions",
|
||||
"extendCharacterDescriptions": {
|
||||
"label": "Characters"
|
||||
|
|
|
|||
|
|
@ -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'];
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
}
|
||||
|
||||
static async #removeMember(_, button) {
|
||||
const update = { [`members.-=${button.dataset.characterId}`]: null };
|
||||
const update = { [`members.${button.dataset.characterId}`]: _del };
|
||||
if (this.data.initiator.id === button.dataset.characterId) {
|
||||
update.iniator = { id: null };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -110,7 +118,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -165,7 +165,8 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
name: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.newDowntimeMove'),
|
||||
img: 'icons/magic/life/cross-worn-green.webp',
|
||||
description: '',
|
||||
actions: []
|
||||
actions: [],
|
||||
effects: []
|
||||
}
|
||||
});
|
||||
} else if (['armorFeatures', 'weaponFeatures'].includes(type)) {
|
||||
|
|
@ -228,7 +229,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
|
||||
});
|
||||
this.render();
|
||||
}
|
||||
|
|
@ -250,7 +251,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;
|
||||
}, {});
|
||||
|
|
@ -310,7 +311,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;
|
||||
}, {})
|
||||
|
|
@ -383,12 +384,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);
|
||||
}
|
||||
|
||||
|
|
@ -435,7 +436,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();
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ export default class SettingFeatureConfig extends HandlebarsApplicationMixin(App
|
|||
}
|
||||
});
|
||||
} else {
|
||||
await this.settings.updateSource({ [`${this.actionsPath}.-=${target.dataset.id}`]: null });
|
||||
await this.settings.updateSource({ [`${this.actionsPath}.${target.dataset.id}`]: _del });
|
||||
}
|
||||
|
||||
this.move = foundry.utils.getProperty(this.settings, this.movePath);
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ 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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@ export default class DhMeasuredTemplate extends foundry.canvas.placeables.Measur
|
|||
|
||||
static getRangeLabels(distanceValue, settings) {
|
||||
let result = { distance: distanceValue, units: '' };
|
||||
const sceneRangeMeasurement = canvas.scene.flags.daggerheart?.rangeMeasurement;
|
||||
if (!settings.enabled) return result;
|
||||
|
||||
const sceneRangeMeasurement = canvas.scene.flags.daggerheart?.rangeMeasurement;
|
||||
const { disable, custom } = CONFIG.DH.GENERAL.sceneRangeMeasurementSetting;
|
||||
if (sceneRangeMeasurement?.setting === disable.id) {
|
||||
result.distance = distanceValue;
|
||||
|
|
@ -27,31 +28,9 @@ export default class DhMeasuredTemplate extends foundry.canvas.placeables.Measur
|
|||
return result;
|
||||
}
|
||||
|
||||
const melee = sceneRangeMeasurement?.setting === custom.id ? sceneRangeMeasurement.melee : settings.melee;
|
||||
const veryClose =
|
||||
sceneRangeMeasurement?.setting === custom.id ? sceneRangeMeasurement.veryClose : settings.veryClose;
|
||||
const close = sceneRangeMeasurement?.setting === custom.id ? sceneRangeMeasurement.close : settings.close;
|
||||
const far = sceneRangeMeasurement?.setting === custom.id ? sceneRangeMeasurement.far : settings.far;
|
||||
if (distanceValue <= melee) {
|
||||
result.distance = game.i18n.localize('DAGGERHEART.CONFIG.Range.melee.name');
|
||||
return result;
|
||||
}
|
||||
if (distanceValue <= veryClose) {
|
||||
result.distance = game.i18n.localize('DAGGERHEART.CONFIG.Range.veryClose.name');
|
||||
return result;
|
||||
}
|
||||
if (distanceValue <= close) {
|
||||
result.distance = game.i18n.localize('DAGGERHEART.CONFIG.Range.close.name');
|
||||
return result;
|
||||
}
|
||||
if (distanceValue <= far) {
|
||||
result.distance = game.i18n.localize('DAGGERHEART.CONFIG.Range.far.name');
|
||||
return result;
|
||||
}
|
||||
if (distanceValue > far) {
|
||||
result.distance = game.i18n.localize('DAGGERHEART.CONFIG.Range.veryFar.name');
|
||||
}
|
||||
|
||||
const ranges = sceneRangeMeasurement?.setting === custom.id ? sceneRangeMeasurement : settings;
|
||||
const distanceKey = ['melee', 'veryClose', 'close', 'far'].find(r => ranges[r] >= distanceValue);
|
||||
result.distance = game.i18n.localize(`DAGGERHEART.CONFIG.Range.${distanceKey ?? 'veryFar'}.name`);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import DhMeasuredTemplate from './measuredTemplate.mjs';
|
||||
|
||||
export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||
/** @inheritdoc */
|
||||
async _draw(options) {
|
||||
|
|
@ -78,6 +80,60 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
|||
return canvas.grid.measurePath([adjustedOriginPoint, adjustDestinationPoint]).distance;
|
||||
}
|
||||
|
||||
_onHoverIn(event, options) {
|
||||
super._onHoverIn(event, options);
|
||||
|
||||
// Check if the setting is enabled
|
||||
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance).showTokenDistance;
|
||||
if (setting === 'never' || (setting === 'encounters' && !game.combat?.started)) return;
|
||||
|
||||
// Check if this token isn't invisible and is actually being hovered
|
||||
const isTokenValid =
|
||||
this.visible &&
|
||||
this.hover &&
|
||||
!this.isPreview &&
|
||||
!this.document.isSecret &&
|
||||
!this.controlled &&
|
||||
!this.animation;
|
||||
if (!isTokenValid) return;
|
||||
|
||||
// Ensure we have a single controlled token
|
||||
const originToken = canvas.tokens.controlled[0];
|
||||
if (!originToken || canvas.tokens.controlled.length > 1) return;
|
||||
|
||||
// Determine the actual range
|
||||
const ranges = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.variantRules).rangeMeasurement;
|
||||
const distanceNum = originToken.distanceTo(this);
|
||||
const distanceResult = DhMeasuredTemplate.getRangeLabels(distanceNum, ranges);
|
||||
const distanceLabel = `${distanceResult.distance} ${distanceResult.units}`.trim();
|
||||
|
||||
// Create the element
|
||||
const element = document.createElement('div');
|
||||
element.id = 'token-hover-distance';
|
||||
element.classList.add('waypoint-label', 'last');
|
||||
const ruler = document.createElement('i');
|
||||
ruler.classList.add('fa-solid', 'fa-ruler');
|
||||
element.appendChild(ruler);
|
||||
const labelEl = document.createElement('span');
|
||||
labelEl.classList.add('total-measurement');
|
||||
labelEl.textContent = distanceLabel;
|
||||
element.appendChild(labelEl);
|
||||
|
||||
// Position the element and add to the DOM
|
||||
const center = this.getCenterPoint();
|
||||
element.style.setProperty('--transformY', 'calc(-100% - 10px)');
|
||||
element.style.setProperty('--position-y', `${this.y}px`);
|
||||
element.style.setProperty('--position-x', `${center.x}px`);
|
||||
element.style.setProperty('--ui-scale', String(canvas.dimensions.uiScale));
|
||||
document.querySelector('#token-hover-distance')?.remove();
|
||||
document.querySelector('#measurement').appendChild(element);
|
||||
}
|
||||
|
||||
_onHoverOut(...args) {
|
||||
super._onHoverOut(...args);
|
||||
document.querySelector('#token-hover-distance')?.remove();
|
||||
}
|
||||
|
||||
/** Returns the point at which a line starting at origin and ending at destination intersects the edge of the bounds */
|
||||
#getEdgeBoundary(bounds, originPoint, destinationPoint) {
|
||||
const points = [
|
||||
|
|
|
|||
|
|
@ -256,7 +256,8 @@ export const defaultRestOptions = {
|
|||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
effects: []
|
||||
},
|
||||
clearStress: {
|
||||
id: 'clearStress',
|
||||
|
|
@ -289,7 +290,8 @@ export const defaultRestOptions = {
|
|||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
effects: []
|
||||
},
|
||||
repairArmor: {
|
||||
id: 'repairArmor',
|
||||
|
|
@ -322,7 +324,8 @@ export const defaultRestOptions = {
|
|||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
effects: []
|
||||
},
|
||||
prepare: {
|
||||
id: 'prepare',
|
||||
|
|
@ -330,7 +333,8 @@ export const defaultRestOptions = {
|
|||
icon: 'fa-solid fa-dumbbell',
|
||||
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.prepare.description'),
|
||||
actions: {}
|
||||
actions: {},
|
||||
effects: []
|
||||
}
|
||||
}),
|
||||
longRest: () => ({
|
||||
|
|
@ -365,7 +369,8 @@ export const defaultRestOptions = {
|
|||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
effects: []
|
||||
},
|
||||
clearStress: {
|
||||
id: 'clearStress',
|
||||
|
|
@ -398,7 +403,8 @@ export const defaultRestOptions = {
|
|||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
effects: []
|
||||
},
|
||||
repairArmor: {
|
||||
id: 'repairArmor',
|
||||
|
|
@ -431,7 +437,8 @@ export const defaultRestOptions = {
|
|||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
effects: []
|
||||
},
|
||||
prepare: {
|
||||
id: 'prepare',
|
||||
|
|
@ -439,7 +446,8 @@ export const defaultRestOptions = {
|
|||
icon: 'fa-solid fa-dumbbell',
|
||||
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.prepare.description'),
|
||||
actions: {}
|
||||
actions: {},
|
||||
effects: []
|
||||
},
|
||||
workOnAProject: {
|
||||
id: 'workOnAProject',
|
||||
|
|
@ -447,7 +455,8 @@ export const defaultRestOptions = {
|
|||
icon: 'fa-solid fa-diagram-project',
|
||||
img: 'icons/skills/social/thumbsup-approval-like.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.workOnAProject.description'),
|
||||
actions: {}
|
||||
actions: {},
|
||||
effects: []
|
||||
}
|
||||
})
|
||||
};
|
||||
|
|
|
|||
|
|
@ -114,9 +114,24 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
|||
* Return Item the action is attached too.
|
||||
*/
|
||||
get item() {
|
||||
if (!this.parent.parent && this.systemPath)
|
||||
return foundry.utils.getProperty(this.parent, this.systemPath).get(this.id);
|
||||
|
||||
return this.parent.parent;
|
||||
}
|
||||
|
||||
get applyEffects() {
|
||||
if (this.item.systemPath) {
|
||||
const itemEffectIds = this.item.effects.map(x => x._id);
|
||||
const movePathSplit = this.item.systemPath.split('.');
|
||||
movePathSplit.pop();
|
||||
const move = foundry.utils.getProperty(this.parent, movePathSplit.join('.'));
|
||||
return new Collection(itemEffectIds.map(id => [id, move.effects.find(x => x.id === id)]));
|
||||
}
|
||||
|
||||
return this.item.effects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first Actor parent found.
|
||||
*/
|
||||
|
|
@ -125,7 +140,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
|||
? this.item
|
||||
: this.item?.parent instanceof DhpActor
|
||||
? this.item.parent
|
||||
: this.item?.actor;
|
||||
: null;
|
||||
}
|
||||
|
||||
static getRollType(parent) {
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ export default class BeastformEffect extends BaseEffect {
|
|||
token.flags.daggerheart?.beastformSubjectTexture ?? this.characterTokenData.tokenRingImg
|
||||
}
|
||||
},
|
||||
'flags.daggerheart': { '-=beastformTokenImg': null, '-=beastformSubjectTexture': null }
|
||||
'flags.daggerheart': { beastformTokenImg: _del, beastformSubjectTexture: _del }
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -169,9 +169,7 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
|
|||
const tagTeam = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.TagTeamRoll);
|
||||
await tagTeam.updateSource({
|
||||
initiator: this.parent.id === tagTeam.initiator ? null : tagTeam.initiator,
|
||||
members: Object.keys(tagTeam.members).find(x => x === this.parent.id)
|
||||
? { [`-=${this.parent.id}`]: null }
|
||||
: {}
|
||||
members: Object.keys(tagTeam.members).find(x => x === this.parent.id) ? { [this.parent.id]: _del } : {}
|
||||
});
|
||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.TagTeamRoll, tagTeam);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export default class DhParty extends BaseDataActor {
|
|||
initiator: this.partyMembers.some(x => x.id === tagTeam.initiator) ? null : tagTeam.initiator,
|
||||
members: Object.keys(tagTeam.members).reduce((acc, key) => {
|
||||
if (this.partyMembers.find(x => x.id === key)) {
|
||||
acc[`-=${key}`] = null;
|
||||
acc[key] = _del;
|
||||
}
|
||||
|
||||
return acc;
|
||||
|
|
|
|||
|
|
@ -3,5 +3,4 @@ export { default as FormulaField } from './formulaField.mjs';
|
|||
export { default as ForeignDocumentUUIDField } from './foreignDocumentUUIDField.mjs';
|
||||
export { default as ForeignDocumentUUIDArrayField } from './foreignDocumentUUIDArrayField.mjs';
|
||||
export { default as TriggerField } from './triggerField.mjs';
|
||||
export { default as MappingField } from './mappingField.mjs';
|
||||
export * as ActionFields from './action/_module.mjs';
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ export default class EffectsField extends fields.ArrayField {
|
|||
});
|
||||
|
||||
effects.forEach(async e => {
|
||||
const effect = this.item.effects.get(e._id);
|
||||
const effect = (this.item.applyEffects ?? this.item.effects).get(e._id);
|
||||
if (!token.actor || !effect) return;
|
||||
await EffectsField.applyEffect(effect, token.actor);
|
||||
});
|
||||
|
|
@ -96,7 +96,7 @@ export default class EffectsField extends fields.ArrayField {
|
|||
content: await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/ui/chat/effectSummary.hbs',
|
||||
{
|
||||
effects: this.effects.map(e => this.item.effects.get(e._id)),
|
||||
effects: this.effects.map(e => (this.item.applyEffects ?? this.item.effects).get(e._id)),
|
||||
targets: messageTargets
|
||||
}
|
||||
)
|
||||
|
|
@ -123,7 +123,7 @@ export default class EffectsField extends fields.ArrayField {
|
|||
|
||||
// Otherwise, create a new effect on the target
|
||||
const effectData = foundry.utils.mergeObject({
|
||||
...effect.toObject(),
|
||||
...(effect.toObject?.() ?? effect),
|
||||
disabled: false,
|
||||
transfer: false,
|
||||
origin: effect.uuid
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import DHActionConfig from '../../applications/sheets-configs/action-config.mjs';
|
||||
import { itemAbleRollParse } from '../../helpers/utils.mjs';
|
||||
import MappingField from './mappingField.mjs';
|
||||
|
||||
/**
|
||||
* Specialized collection type for stored actions.
|
||||
|
|
@ -11,9 +10,9 @@ export class ActionCollection extends Collection {
|
|||
constructor(model, entries) {
|
||||
super();
|
||||
this.#model = model;
|
||||
for (const entry of entries) {
|
||||
if (!(entry instanceof game.system.api.models.actions.actionsTypes.base)) continue;
|
||||
this.set(entry._id, entry);
|
||||
for (const [key, value] of entries) {
|
||||
if (!(value instanceof game.system.api.models.actions.actionsTypes.base)) continue;
|
||||
this.set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,7 +60,7 @@ export class ActionCollection extends Collection {
|
|||
/**
|
||||
* Field that stores actions.
|
||||
*/
|
||||
export class ActionsField extends MappingField {
|
||||
export class ActionsField extends foundry.data.fields.TypedObjectField {
|
||||
constructor(options) {
|
||||
super(new ActionField(), options);
|
||||
}
|
||||
|
|
@ -70,7 +69,7 @@ export class ActionsField extends MappingField {
|
|||
|
||||
/** @inheritDoc */
|
||||
initialize(value, model, options) {
|
||||
const actions = Object.values(super.initialize(value, model, options));
|
||||
const actions = Object.entries(super.initialize(value, model, options));
|
||||
return new ActionCollection(model, actions);
|
||||
}
|
||||
}
|
||||
|
|
@ -160,6 +159,7 @@ export function ActionMixin(Base) {
|
|||
}
|
||||
|
||||
get uuid() {
|
||||
if (!(this.item instanceof game.system.api.documents.DHItem)) return null;
|
||||
return `${this.item.uuid}.${this.documentName}.${this.id}`;
|
||||
}
|
||||
|
||||
|
|
@ -243,11 +243,11 @@ export function ActionMixin(Base) {
|
|||
: foundry.utils.getProperty(result, basePath);
|
||||
}
|
||||
|
||||
delete() {
|
||||
async delete() {
|
||||
if (!this.inCollection) return this.item;
|
||||
const action = foundry.utils.getProperty(this.item, `system.${this.systemPath}`)?.get(this.id);
|
||||
if (!action) return this.item;
|
||||
this.item.update({ [`system.${this.systemPath}.-=${this.id}`]: null });
|
||||
await this.item.update({ [`system.${this.systemPath}.${this.id}`]: _del }); // Does not work. Unsure why. It worked in v13 <_<'
|
||||
this.constructor._sheets.get(this.uuid)?.close();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,128 +0,0 @@
|
|||
/**
|
||||
* A subclass of ObjectField that represents a mapping of keys to the provided DataField type.
|
||||
*
|
||||
* @param {DataField} model The class of DataField which should be embedded in this field.
|
||||
* @param {MappingFieldOptions} [options={}] Options which configure the behavior of the field.
|
||||
* @property {string[]} [initialKeys] Keys that will be created if no data is provided.
|
||||
* @property {MappingFieldInitialValueBuilder} [initialValue] Function to calculate the initial value for a key.
|
||||
* @property {boolean} [initialKeysOnly=false] Should the keys in the initialized data be limited to the keys provided
|
||||
* by `options.initialKeys`?
|
||||
*/
|
||||
export default class MappingField extends foundry.data.fields.ObjectField {
|
||||
constructor(model, options) {
|
||||
if (!(model instanceof foundry.data.fields.DataField)) {
|
||||
throw new Error('MappingField must have a DataField as its contained element');
|
||||
}
|
||||
super(options);
|
||||
|
||||
/**
|
||||
* The embedded DataField definition which is contained in this field.
|
||||
* @type {DataField}
|
||||
*/
|
||||
this.model = model;
|
||||
model.parent = this;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @inheritDoc */
|
||||
static get _defaults() {
|
||||
return foundry.utils.mergeObject(super._defaults, {
|
||||
initialKeys: null,
|
||||
initialValue: null,
|
||||
initialKeysOnly: false
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @inheritDoc */
|
||||
_cleanType(value, options) {
|
||||
Object.entries(value).forEach(([k, v]) => {
|
||||
if (k.startsWith('-=')) return;
|
||||
value[k] = this.model.clean(v, options);
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @inheritDoc */
|
||||
getInitialValue(data) {
|
||||
let keys = this.initialKeys;
|
||||
const initial = super.getInitialValue(data);
|
||||
if (!keys || !foundry.utils.isEmpty(initial)) return initial;
|
||||
if (!(keys instanceof Array)) keys = Object.keys(keys);
|
||||
for (const key of keys) initial[key] = this._getInitialValueForKey(key);
|
||||
return initial;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get the initial value for the provided key.
|
||||
* @param {string} key Key within the object being built.
|
||||
* @param {object} [object] Any existing mapping data.
|
||||
* @returns {*} Initial value based on provided field type.
|
||||
*/
|
||||
_getInitialValueForKey(key, object) {
|
||||
const initial = this.model.getInitialValue();
|
||||
return this.initialValue?.(key, initial, object) ?? initial;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
_validateType(value, options = {}) {
|
||||
if (foundry.utils.getType(value) !== 'Object') throw new Error('must be an Object');
|
||||
const errors = this._validateValues(value, options);
|
||||
if (!foundry.utils.isEmpty(errors)) {
|
||||
const failure = new foundry.data.validation.DataModelValidationFailure();
|
||||
failure.elements = Object.entries(errors).map(([id, failure]) => ({ id, failure }));
|
||||
throw failure.asError();
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Validate each value of the object.
|
||||
* @param {object} value The object to validate.
|
||||
* @param {object} options Validation options.
|
||||
* @returns {Record<string, Error>} An object of value-specific errors by key.
|
||||
*/
|
||||
_validateValues(value, options) {
|
||||
const errors = {};
|
||||
for (const [k, v] of Object.entries(value)) {
|
||||
if (k.startsWith('-=')) continue;
|
||||
const error = this.model.validate(v, options);
|
||||
if (error) errors[k] = error;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
initialize(value, model, options = {}) {
|
||||
if (!value) return value;
|
||||
const obj = {};
|
||||
const initialKeys = this.initialKeys instanceof Array ? this.initialKeys : Object.keys(this.initialKeys ?? {});
|
||||
const keys = this.initialKeysOnly ? initialKeys : Object.keys(value);
|
||||
for (const key of keys) {
|
||||
const data = value[key] ?? this._getInitialValueForKey(key, value);
|
||||
obj[key] = this.model.initialize(data, model, options);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @inheritDoc */
|
||||
_getField(path) {
|
||||
if (path.length === 0) return this;
|
||||
else if (path.length === 1) return this.model;
|
||||
path.shift();
|
||||
return this.model._getField(path);
|
||||
}
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ export default class DHArmor extends AttachableItem {
|
|||
}
|
||||
await this.parent.deleteEmbeddedDocuments('ActiveEffect', effectIds);
|
||||
changes.system.actions = actionIds.reduce((acc, id) => {
|
||||
acc[`-=${id}`] = null;
|
||||
acc[id] = _del;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
|
|
|
|||
|
|
@ -230,9 +230,9 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
|
|||
|
||||
if (changed.system?.actions) {
|
||||
const triggersToRemove = Object.keys(changed.system.actions).reduce((acc, key) => {
|
||||
if (!changed.system.actions[key]) {
|
||||
const strippedKey = key.replace('-=', '');
|
||||
acc.push(...this.actions.get(strippedKey).triggers.map(x => x.trigger));
|
||||
const action = changed.system.actions[key];
|
||||
if (action && Object.keys(action).length === 0) {
|
||||
acc.push(...this.actions.get(key).triggers.map(x => x.trigger));
|
||||
}
|
||||
|
||||
return acc;
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ export default class DHWeapon extends AttachableItem {
|
|||
|
||||
await this.parent.deleteEmbeddedDocuments('ActiveEffect', removedEffectsUpdate);
|
||||
changes.system.actions = removedActionsUpdate.reduce((acc, id) => {
|
||||
acc[`-=${id}`] = null;
|
||||
acc[id] = _del;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,25 @@ export default class DhAppearance extends foundry.abstract.DataModel {
|
|||
damage: new BooleanField(),
|
||||
target: new BooleanField()
|
||||
}),
|
||||
showTokenDistance: new StringField({
|
||||
required: true,
|
||||
choices: {
|
||||
always: {
|
||||
value: 'always',
|
||||
label: 'DAGGERHEART.SETTINGS.Appearance.FIELDS.showTokenDistance.choices.always'
|
||||
},
|
||||
encounters: {
|
||||
value: 'encounters',
|
||||
label: 'DAGGERHEART.SETTINGS.Appearance.FIELDS.showTokenDistance.choices.encounters'
|
||||
},
|
||||
never: {
|
||||
value: 'never',
|
||||
label: 'DAGGERHEART.SETTINGS.Appearance.FIELDS.showTokenDistance.choices.never'
|
||||
}
|
||||
},
|
||||
nullable: false,
|
||||
initial: 'always'
|
||||
}),
|
||||
hideAttribution: new BooleanField(),
|
||||
showGenericStatusEffects: new BooleanField({ initial: true })
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,20 @@ const currencyField = (initial, label, icon) =>
|
|||
icon: new foundry.data.fields.StringField({ required: true, nullable: false, blank: true, initial: icon })
|
||||
});
|
||||
|
||||
const restMoveField = () =>
|
||||
new foundry.data.fields.SchemaField({
|
||||
name: new foundry.data.fields.StringField({ required: true }),
|
||||
icon: new foundry.data.fields.StringField({ required: true }),
|
||||
img: new foundry.data.fields.FilePathField({
|
||||
initial: 'icons/magic/life/cross-worn-green.webp',
|
||||
categories: ['IMAGE'],
|
||||
base64: false
|
||||
}),
|
||||
description: new foundry.data.fields.HTMLField(),
|
||||
actions: new ActionsField(),
|
||||
effects: new foundry.data.fields.ArrayField(new foundry.data.fields.ObjectField())
|
||||
});
|
||||
|
||||
export default class DhHomebrew extends foundry.abstract.DataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
|
|
@ -105,37 +119,11 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
|
|||
restMoves: new fields.SchemaField({
|
||||
longRest: new fields.SchemaField({
|
||||
nrChoices: new fields.NumberField({ required: true, integer: true, min: 1, initial: 2 }),
|
||||
moves: new fields.TypedObjectField(
|
||||
new fields.SchemaField({
|
||||
name: new fields.StringField({ required: true }),
|
||||
icon: new fields.StringField({ required: true }),
|
||||
img: new fields.FilePathField({
|
||||
initial: 'icons/magic/life/cross-worn-green.webp',
|
||||
categories: ['IMAGE'],
|
||||
base64: false
|
||||
}),
|
||||
description: new fields.HTMLField(),
|
||||
actions: new ActionsField()
|
||||
}),
|
||||
{ initial: defaultRestOptions.longRest() }
|
||||
)
|
||||
moves: new fields.TypedObjectField(restMoveField(), { initial: defaultRestOptions.longRest() })
|
||||
}),
|
||||
shortRest: new fields.SchemaField({
|
||||
nrChoices: new fields.NumberField({ required: true, integer: true, min: 1, initial: 2 }),
|
||||
moves: new fields.TypedObjectField(
|
||||
new fields.SchemaField({
|
||||
name: new fields.StringField({ required: true }),
|
||||
icon: new fields.StringField({ required: true }),
|
||||
img: new fields.FilePathField({
|
||||
initial: 'icons/magic/life/cross-worn-green.webp',
|
||||
categories: ['IMAGE'],
|
||||
base64: false
|
||||
}),
|
||||
description: new fields.HTMLField(),
|
||||
actions: new ActionsField()
|
||||
}),
|
||||
{ initial: defaultRestOptions.shortRest() }
|
||||
)
|
||||
moves: new fields.TypedObjectField(restMoveField(), { initial: defaultRestOptions.shortRest() })
|
||||
})
|
||||
}),
|
||||
domains: new fields.TypedObjectField(
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ export default class DhpActor extends Actor {
|
|||
}
|
||||
|
||||
const updatedLevelups = Object.keys(this.system.levelData.levelups).reduce((acc, level) => {
|
||||
if (Number(level) > usedLevel) acc[`-=${level}`] = null;
|
||||
if (Number(level) > usedLevel) acc[level] = _del;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
|
@ -187,7 +187,7 @@ export default class DhpActor extends Actor {
|
|||
if (experiences.length > 0) {
|
||||
const getUpdate = () => ({
|
||||
'system.experiences': experiences.reduce((acc, key) => {
|
||||
acc[`-=${key}`] = null;
|
||||
acc[key] = _del;
|
||||
return acc;
|
||||
}, {})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ export default class DHToken extends CONFIG.Token.documentClass {
|
|||
|
||||
// Hexagon symmetry
|
||||
if (columns) {
|
||||
const rowData = BaseToken.#getHexagonalShape(height, width, shape, false);
|
||||
const rowData = DHToken.#getHexagonalShape(height, width, shape, false);
|
||||
if (!rowData) return null;
|
||||
|
||||
// Transpose the offsets/points of the shape in row orientation
|
||||
|
|
|
|||
|
|
@ -171,10 +171,10 @@ export const getDeleteKeys = (property, innerProperty, innerPropertyDefaultValue
|
|||
[innerProperty]: innerPropertyDefaultValue
|
||||
};
|
||||
} else {
|
||||
acc[`${key}.-=${innerProperty}`] = null;
|
||||
acc[`${key}.${innerProperty}`] = _del;
|
||||
}
|
||||
} else {
|
||||
acc[`-=${key}`] = null;
|
||||
acc[`${key}`] = _del;
|
||||
}
|
||||
|
||||
return acc;
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ export async function runMigrations() {
|
|||
const initatorMissing = tagTeam.initiator && !game.actors.some(actor => actor.id === tagTeam.initiator);
|
||||
const missingMembers = Object.keys(tagTeam.members).reduce((acc, id) => {
|
||||
if (!game.actors.some(actor => actor.id === id)) {
|
||||
acc[`-=${id}`] = null;
|
||||
acc[id] = _del;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
.application.sheet.scene-config {
|
||||
.sheet-tabs.tabs {
|
||||
font-size: 12px;
|
||||
|
||||
a[data-tab='dh'] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@
|
|||
value=setting.showGenericStatusEffects
|
||||
localize=true}}
|
||||
{{formGroup
|
||||
fields.showTokenDistance
|
||||
value=setting.showTokenDistance
|
||||
localize=true}}
|
||||
{{formGroup
|
||||
fields.hideAttribution
|
||||
value=setting.hideAttribution
|
||||
localize=true}}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,40 @@
|
|||
|
||||
|
||||
<nav id="scene-navigation" aria-roledescription="{{localize "SCENE_NAVIGATION.LABEL"}}" data-tooltip-direction="RIGHT">
|
||||
{{#if canExpand}}
|
||||
<a id="scene-navigation-expand" class="ui-control" data-action="toggleExpand">
|
||||
<i class="fa-solid fa-caret-down" inert></i>
|
||||
</a>
|
||||
{{/if}}
|
||||
{{#with scenes.viewed}}
|
||||
<menu id="scene-navigation-viewed" class="scene-navigation-menu flexcol">
|
||||
{{> ".scene" }}
|
||||
</menu>
|
||||
{{/with}}
|
||||
<menu id="scene-navigation-levels" class="scene-levels scene-navigation-menu flexcol levels-{{ scenes.levels.length }}">
|
||||
{{#each scenes.levels}}
|
||||
<li class="level-row">
|
||||
{{#with button}}
|
||||
<button type="button" class="ui-control icon fa-solid {{ css }}" data-action="cycleLevel"
|
||||
data-direction="{{ direction }}" aria-label="{{ label }}"></button>
|
||||
{{/with}}
|
||||
<div class="ui-control scene scene-level {{ css }}" data-scene-id="{{ sceneId }}" data-level-id="{{ id }}" data-action="viewLevel">
|
||||
<span class="ellipsis">{{ name }}</span>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</menu>
|
||||
<menu id="scene-navigation-active" class="scene-navigation-menu flexcol">
|
||||
{{#each scenes.active}}
|
||||
{{> ".scene" }}
|
||||
{{/each}}
|
||||
</menu>
|
||||
<menu id="scene-navigation-inactive" class="scene-navigation-menu flexcol">
|
||||
{{#each scenes.inactive as |scene|}}
|
||||
{{> ".scene" }}
|
||||
{{/each}}
|
||||
</menu>
|
||||
{{!-- <menu id="scene-navigation-active" class="scene-navigation-menu flexcol">
|
||||
{{#each scenes.active as |scene|}}
|
||||
<li class="scene-wrapper">
|
||||
<div class="ui-control scene {{scene.cssClass}}" data-scene-id="{{scene.id}}" data-action="viewScene" {{#if scene.tooltip}}data-tooltip-text="{{scene.tooltip}}"{{/if}}>
|
||||
|
|
@ -32,5 +62,25 @@
|
|||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</menu>
|
||||
</menu> --}}
|
||||
</nav>
|
||||
|
||||
{{#*inline ".scene"}}
|
||||
<li class="scene-wrapper">
|
||||
<div class="ui-control scene {{ cssClass }}" data-scene-id="{{ id }}" data-action="viewScene" {{#if tooltip}}data-tooltip-text="{{ tooltip }}"{{/if}}>
|
||||
<span class="scene-name ellipsis">{{ name }}</span>
|
||||
{{#if users}}
|
||||
<ul class="scene-players">
|
||||
{{#each users}}
|
||||
<li class="scene-player" style="--color-bg: {{ color }}; --color-border: {{ border }}" data-tooltip
|
||||
aria-label="{{ name }}">{{ letter }}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if hasEnvironments}}
|
||||
<button class="ui-control scene-environment {{#if (gt environments.length 1)}}many-environments{{/if}}" data-action="openSceneEnvironment" data-scene-id="{{id}}"><img src="{{environmentImage}}" /> </button>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/inline}}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue