mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-14 12:41:07 +01:00
146 - Measured Templates (#147)
* Added DhMeasuredTemplate * Added TemplateEnricher for Template buttons in text
This commit is contained in:
parent
7802d18a4d
commit
96ed90b5fc
9 changed files with 168 additions and 66 deletions
|
|
@ -9,12 +9,15 @@ import { registerDHSettings } from './module/applications/settings.mjs';
|
||||||
import DhpChatLog from './module/ui/chatLog.mjs';
|
import DhpChatLog from './module/ui/chatLog.mjs';
|
||||||
import DhpRuler from './module/ui/ruler.mjs';
|
import DhpRuler from './module/ui/ruler.mjs';
|
||||||
import DhpTokenRuler from './module/ui/tokenRuler.mjs';
|
import DhpTokenRuler from './module/ui/tokenRuler.mjs';
|
||||||
import { dualityRollEnricher } from './module/enrichers/DualityRollEnricher.mjs';
|
import { DhDualityRollEnricher, DhTemplateEnricher } from './module/enrichers/_module.mjs';
|
||||||
import { getCommandTarget, rollCommandToJSON, setDiceSoNiceForDualityRoll } from './module/helpers/utils.mjs';
|
import { getCommandTarget, rollCommandToJSON, setDiceSoNiceForDualityRoll } from './module/helpers/utils.mjs';
|
||||||
import { abilities } from './module/config/actorConfig.mjs';
|
import { abilities } from './module/config/actorConfig.mjs';
|
||||||
import Resources from './module/applications/resources.mjs';
|
import Resources from './module/applications/resources.mjs';
|
||||||
import DHDualityRoll from './module/data/chat-message/dualityRoll.mjs';
|
import DHDualityRoll from './module/data/chat-message/dualityRoll.mjs';
|
||||||
import { DualityRollColor } from './module/data/settings/Appearance.mjs';
|
import { DualityRollColor } from './module/data/settings/Appearance.mjs';
|
||||||
|
import { DhMeasuredTemplate } from './module/placeables/_module.mjs';
|
||||||
|
import { renderDualityButton } from './module/enrichers/DualityRollEnricher.mjs';
|
||||||
|
import { renderMeasuredTemplate } from './module/enrichers/TemplateEnricher.mjs';
|
||||||
|
|
||||||
globalThis.SYSTEM = SYSTEM;
|
globalThis.SYSTEM = SYSTEM;
|
||||||
|
|
||||||
|
|
@ -27,16 +30,26 @@ Hooks.once('init', () => {
|
||||||
documents
|
documents
|
||||||
};
|
};
|
||||||
|
|
||||||
CONFIG.TextEditor.enrichers.push({
|
CONFIG.TextEditor.enrichers.push(
|
||||||
pattern: /\[\[\/dr\s?(.*?)\]\]/g,
|
...[
|
||||||
enricher: dualityRollEnricher
|
{
|
||||||
});
|
pattern: /\[\[\/dr\s?(.*?)\]\]/g,
|
||||||
|
enricher: DhDualityRollEnricher
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: /^@Template\[(.*)\]$/g,
|
||||||
|
enricher: DhTemplateEnricher
|
||||||
|
}
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
CONFIG.statusEffects = Object.values(SYSTEM.GENERAL.conditions).map(x => ({
|
CONFIG.statusEffects = Object.values(SYSTEM.GENERAL.conditions).map(x => ({
|
||||||
...x,
|
...x,
|
||||||
name: game.i18n.localize(x.name)
|
name: game.i18n.localize(x.name)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
CONFIG.MeasuredTemplate.objectClass = DhMeasuredTemplate;
|
||||||
|
|
||||||
CONFIG.Item.documentClass = documents.DhpItem;
|
CONFIG.Item.documentClass = documents.DhpItem;
|
||||||
|
|
||||||
//Registering the Item DataModel
|
//Registering the Item DataModel
|
||||||
|
|
@ -141,43 +154,34 @@ Hooks.on(socketEvent.GMUpdate, async (action, uuid, update) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const renderDualityButton = async event => {
|
|
||||||
const button = event.currentTarget,
|
|
||||||
traitValue = button.dataset.trait?.toLowerCase(),
|
|
||||||
target = getCommandTarget();
|
|
||||||
if (!target) return;
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
event: event,
|
|
||||||
title: button.dataset.title,
|
|
||||||
roll: {
|
|
||||||
modifier: traitValue ? target.system.traits[traitValue].value : null,
|
|
||||||
label: button.dataset.label,
|
|
||||||
type: button.dataset.actionType ?? null // Need check
|
|
||||||
},
|
|
||||||
chatMessage: {
|
|
||||||
template: 'systems/daggerheart/templates/chat/duality-roll.hbs'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
await target.diceRoll(config);
|
|
||||||
};
|
|
||||||
|
|
||||||
Hooks.on('renderChatMessageHTML', (_, element) => {
|
Hooks.on('renderChatMessageHTML', (_, element) => {
|
||||||
element
|
element
|
||||||
.querySelectorAll('.duality-roll-button')
|
.querySelectorAll('.duality-roll-button')
|
||||||
.forEach(element => element.addEventListener('click', renderDualityButton));
|
.forEach(element => element.addEventListener('click', renderDualityButton));
|
||||||
|
|
||||||
|
element
|
||||||
|
.querySelectorAll('.measured-template-button')
|
||||||
|
.forEach(element => element.addEventListener('click', renderMeasuredTemplate));
|
||||||
});
|
});
|
||||||
|
|
||||||
Hooks.on('renderJournalEntryPageProseMirrorSheet', (_, element) => {
|
Hooks.on('renderJournalEntryPageProseMirrorSheet', (_, element) => {
|
||||||
element
|
element
|
||||||
.querySelectorAll('.duality-roll-button')
|
.querySelectorAll('.duality-roll-button')
|
||||||
.forEach(element => element.addEventListener('click', renderDualityButton));
|
.forEach(element => element.addEventListener('click', renderDualityButton));
|
||||||
|
|
||||||
|
element
|
||||||
|
.querySelectorAll('.measured-template-button')
|
||||||
|
.forEach(element => element.addEventListener('click', renderMeasuredTemplate));
|
||||||
});
|
});
|
||||||
|
|
||||||
Hooks.on('renderHandlebarsApplication', (_, element) => {
|
Hooks.on('renderHandlebarsApplication', (_, element) => {
|
||||||
element
|
element
|
||||||
.querySelectorAll('.duality-roll-button')
|
.querySelectorAll('.duality-roll-button')
|
||||||
.forEach(element => element.addEventListener('click', renderDualityButton));
|
.forEach(element => element.addEventListener('click', renderDualityButton));
|
||||||
|
|
||||||
|
element
|
||||||
|
.querySelectorAll('.measured-template-button')
|
||||||
|
.forEach(element => element.addEventListener('click', renderMeasuredTemplate));
|
||||||
});
|
});
|
||||||
|
|
||||||
Hooks.on('chatMessage', (_, message) => {
|
Hooks.on('chatMessage', (_, message) => {
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,42 @@
|
||||||
export const range = {
|
export const range = {
|
||||||
self: {
|
self: {
|
||||||
|
id: 'self',
|
||||||
|
short: 's',
|
||||||
label: 'DAGGERHEART.Range.self.name',
|
label: 'DAGGERHEART.Range.self.name',
|
||||||
description: 'DAGGERHEART.Range.self.description',
|
description: 'DAGGERHEART.Range.self.description',
|
||||||
distance: 0
|
distance: 0
|
||||||
},
|
},
|
||||||
melee: {
|
melee: {
|
||||||
id: 'melee',
|
id: 'melee',
|
||||||
|
short: 'm',
|
||||||
label: 'DAGGERHEART.Range.melee.name',
|
label: 'DAGGERHEART.Range.melee.name',
|
||||||
description: 'DAGGERHEART.Range.melee.description',
|
description: 'DAGGERHEART.Range.melee.description',
|
||||||
distance: 1
|
distance: 1
|
||||||
},
|
},
|
||||||
veryClose: {
|
veryClose: {
|
||||||
id: 'veryClose',
|
id: 'veryClose',
|
||||||
|
short: 'vc',
|
||||||
label: 'DAGGERHEART.Range.veryClose.name',
|
label: 'DAGGERHEART.Range.veryClose.name',
|
||||||
description: 'DAGGERHEART.Range.veryClose.description',
|
description: 'DAGGERHEART.Range.veryClose.description',
|
||||||
distance: 3
|
distance: 3
|
||||||
},
|
},
|
||||||
close: {
|
close: {
|
||||||
id: 'close',
|
id: 'close',
|
||||||
|
short: 'c',
|
||||||
label: 'DAGGERHEART.Range.close.name',
|
label: 'DAGGERHEART.Range.close.name',
|
||||||
description: 'DAGGERHEART.Range.close.description',
|
description: 'DAGGERHEART.Range.close.description',
|
||||||
distance: 10
|
distance: 10
|
||||||
},
|
},
|
||||||
far: {
|
far: {
|
||||||
id: 'far',
|
id: 'far',
|
||||||
|
short: 'f',
|
||||||
label: 'DAGGERHEART.Range.far.name',
|
label: 'DAGGERHEART.Range.far.name',
|
||||||
description: 'DAGGERHEART.Range.far.description',
|
description: 'DAGGERHEART.Range.far.description',
|
||||||
distance: 20
|
distance: 20
|
||||||
},
|
},
|
||||||
veryFar: {
|
veryFar: {
|
||||||
id: 'veryFar',
|
id: 'veryFar',
|
||||||
|
short: 'vf',
|
||||||
label: 'DAGGERHEART.Range.veryFar.name',
|
label: 'DAGGERHEART.Range.veryFar.name',
|
||||||
description: 'DAGGERHEART.Range.veryFar.description',
|
description: 'DAGGERHEART.Range.veryFar.description',
|
||||||
distance: 30
|
distance: 30
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { abilities } from '../config/actorConfig.mjs';
|
import { abilities } from '../config/actorConfig.mjs';
|
||||||
import { rollCommandToJSON } from '../helpers/utils.mjs';
|
import { getCommandTarget, rollCommandToJSON } from '../helpers/utils.mjs';
|
||||||
|
|
||||||
export function dualityRollEnricher(match, _options) {
|
export default function DhDualityRollEnricher(match, _options) {
|
||||||
const roll = rollCommandToJSON(match[1]);
|
const roll = rollCommandToJSON(match[1]);
|
||||||
if (!roll) return match[0];
|
if (!roll) return match[0];
|
||||||
|
|
||||||
|
|
@ -39,3 +39,24 @@ export function getDualityMessage(roll) {
|
||||||
|
|
||||||
return dualityElement;
|
return dualityElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const renderDualityButton = async event => {
|
||||||
|
const button = event.currentTarget,
|
||||||
|
traitValue = button.dataset.trait?.toLowerCase(),
|
||||||
|
target = getCommandTarget();
|
||||||
|
if (!target) return;
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
event: event,
|
||||||
|
title: button.dataset.title,
|
||||||
|
roll: {
|
||||||
|
modifier: traitValue ? target.system.traits[traitValue].value : null,
|
||||||
|
label: button.dataset.label,
|
||||||
|
type: button.dataset.actionType ?? null // Need check
|
||||||
|
},
|
||||||
|
chatMessage: {
|
||||||
|
template: 'systems/daggerheart/templates/chat/duality-roll.hbs'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await target.diceRoll(config);
|
||||||
|
};
|
||||||
|
|
|
||||||
60
module/enrichers/TemplateEnricher.mjs
Normal file
60
module/enrichers/TemplateEnricher.mjs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { range as configRange } from '../config/generalConfig.mjs';
|
||||||
|
|
||||||
|
export default function DhTemplateEnricher(match, _options) {
|
||||||
|
const parts = match[1].split('|').map(x => x.trim());
|
||||||
|
|
||||||
|
let type = null,
|
||||||
|
range = null;
|
||||||
|
|
||||||
|
parts.forEach(part => {
|
||||||
|
const split = part.split(':').map(x => x.toLowerCase().trim());
|
||||||
|
if (split.length === 2) {
|
||||||
|
switch (split[0]) {
|
||||||
|
case 'type':
|
||||||
|
const matchedType = Object.values(CONST.MEASURED_TEMPLATE_TYPES).find(
|
||||||
|
x => x.toLowerCase() === split[1]
|
||||||
|
);
|
||||||
|
type = matchedType;
|
||||||
|
break;
|
||||||
|
case 'range':
|
||||||
|
const matchedRange = Object.values(configRange).find(
|
||||||
|
x => x.id.toLowerCase() === split[1] || x.short === split[1]
|
||||||
|
);
|
||||||
|
range = matchedRange?.id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!type || !range) return match[0];
|
||||||
|
|
||||||
|
const templateElement = document.createElement('span');
|
||||||
|
templateElement.innerHTML = `
|
||||||
|
<button class="measured-template-button" data-type="${type}" data-range="${range}">
|
||||||
|
${game.i18n.localize(`TEMPLATE.TYPES.${type}`)} - ${game.i18n.localize(`DAGGERHEART.Range.${range}.name`)}
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
|
||||||
|
return templateElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const renderMeasuredTemplate = async event => {
|
||||||
|
const button = event.currentTarget,
|
||||||
|
type = button.dataset.type,
|
||||||
|
range = button.dataset.range;
|
||||||
|
|
||||||
|
if (!type || !range || !game.canvas.scene) return;
|
||||||
|
|
||||||
|
const distance = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.RangeMeasurement)[range];
|
||||||
|
const { width, height } = game.canvas.scene.dimensions;
|
||||||
|
canvas.scene.createEmbeddedDocuments('MeasuredTemplate', [
|
||||||
|
{
|
||||||
|
x: width / 2,
|
||||||
|
y: height / 2,
|
||||||
|
t: type,
|
||||||
|
distance: distance,
|
||||||
|
width: type === CONST.MEASURED_TEMPLATE_TYPES.RAY ? 5 : undefined,
|
||||||
|
angle: type === CONST.MEASURED_TEMPLATE_TYPES.CONE ? CONFIG.MeasuredTemplate.defaults.angle : undefined
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
};
|
||||||
4
module/enrichers/_module.mjs
Normal file
4
module/enrichers/_module.mjs
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
import DhDualityRollEnricher from './DualityRollEnricher.mjs';
|
||||||
|
import DhTemplateEnricher from './TemplateEnricher.mjs';
|
||||||
|
|
||||||
|
export { DhDualityRollEnricher, DhTemplateEnricher };
|
||||||
3
module/placeables/_module.mjs
Normal file
3
module/placeables/_module.mjs
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
import DhMeasuredTemplate from './measuredTemplate.mjs';
|
||||||
|
|
||||||
|
export { DhMeasuredTemplate };
|
||||||
35
module/placeables/measuredTemplate.mjs
Normal file
35
module/placeables/measuredTemplate.mjs
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
export default class DhMeasuredTemplate extends MeasuredTemplate {
|
||||||
|
_refreshRulerText() {
|
||||||
|
super._refreshRulerText();
|
||||||
|
|
||||||
|
const rangeMeasurementSettings = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.RangeMeasurement);
|
||||||
|
if (rangeMeasurementSettings.enabled) {
|
||||||
|
const splitRulerText = this.ruler.text.split(' ');
|
||||||
|
if (splitRulerText.length > 0) {
|
||||||
|
const rulerValue = Number(splitRulerText[0]);
|
||||||
|
const vagueLabel = this.constructor.getDistanceLabel(rulerValue, rangeMeasurementSettings);
|
||||||
|
this.ruler.text = vagueLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static getDistanceLabel(distance, settings) {
|
||||||
|
if (distance <= settings.melee) {
|
||||||
|
return game.i18n.localize('DAGGERHEART.Range.melee.name');
|
||||||
|
}
|
||||||
|
if (distance <= settings.veryClose) {
|
||||||
|
return game.i18n.localize('DAGGERHEART.Range.veryClose.name');
|
||||||
|
}
|
||||||
|
if (distance <= settings.close) {
|
||||||
|
return game.i18n.localize('DAGGERHEART.Range.close.name');
|
||||||
|
}
|
||||||
|
if (distance <= settings.far) {
|
||||||
|
return game.i18n.localize('DAGGERHEART.Range.far.name');
|
||||||
|
}
|
||||||
|
if (distance <= settings.veryFar) {
|
||||||
|
return game.i18n.localize('DAGGERHEART.Range.veryFar.name');
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import DhMeasuredTemplate from '../placeables/measuredTemplate.mjs';
|
||||||
|
|
||||||
export default class DhpRuler extends foundry.canvas.interaction.Ruler {
|
export default class DhpRuler extends foundry.canvas.interaction.Ruler {
|
||||||
_getWaypointLabelContext(waypoint, state) {
|
_getWaypointLabelContext(waypoint, state) {
|
||||||
const context = super._getWaypointLabelContext(waypoint, state);
|
const context = super._getWaypointLabelContext(waypoint, state);
|
||||||
|
|
@ -6,29 +8,11 @@ export default class DhpRuler extends foundry.canvas.interaction.Ruler {
|
||||||
const range = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.RangeMeasurement);
|
const range = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.RangeMeasurement);
|
||||||
|
|
||||||
if (range.enabled) {
|
if (range.enabled) {
|
||||||
const distance = this.#getRangeLabel(waypoint.measurement.distance.toNearest(0.01), range);
|
const distance = DhMeasuredTemplate.getDistanceLabel(waypoint.measurement.distance.toNearest(0.01), range);
|
||||||
context.cost = { total: distance, units: null };
|
context.cost = { total: distance, units: null };
|
||||||
context.distance = { total: distance, units: null };
|
context.distance = { total: distance, units: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
#getRangeLabel(distance, settings) {
|
|
||||||
if (distance <= settings.melee) {
|
|
||||||
return game.i18n.localize('DAGGERHEART.Range.melee.name');
|
|
||||||
}
|
|
||||||
if (distance <= settings.veryClose) {
|
|
||||||
return game.i18n.localize('DAGGERHEART.Range.veryClose.name');
|
|
||||||
}
|
|
||||||
if (distance <= settings.close) {
|
|
||||||
return game.i18n.localize('DAGGERHEART.Range.close.name');
|
|
||||||
}
|
|
||||||
if (distance <= settings.far) {
|
|
||||||
return game.i18n.localize('DAGGERHEART.Range.far.name');
|
|
||||||
}
|
|
||||||
if (distance <= settings.veryFar) {
|
|
||||||
return game.i18n.localize('DAGGERHEART.Range.veryFar.name');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import DhMeasuredTemplate from '../placeables/measuredTemplate.mjs';
|
||||||
|
|
||||||
export default class DhpTokenRuler extends foundry.canvas.placeables.tokens.TokenRuler {
|
export default class DhpTokenRuler extends foundry.canvas.placeables.tokens.TokenRuler {
|
||||||
_getWaypointLabelContext(waypoint, state) {
|
_getWaypointLabelContext(waypoint, state) {
|
||||||
const context = super._getWaypointLabelContext(waypoint, state);
|
const context = super._getWaypointLabelContext(waypoint, state);
|
||||||
|
|
@ -6,29 +8,11 @@ export default class DhpTokenRuler extends foundry.canvas.placeables.tokens.Toke
|
||||||
const range = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.RangeMeasurement);
|
const range = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.RangeMeasurement);
|
||||||
|
|
||||||
if (range.enabled) {
|
if (range.enabled) {
|
||||||
const distance = this.#getRangeLabel(waypoint.measurement.distance.toNearest(0.01), range);
|
const distance = DhMeasuredTemplate.getDistanceLabel(waypoint.measurement.distance.toNearest(0.01), range);
|
||||||
context.cost = { total: distance, units: null };
|
context.cost = { total: distance, units: null };
|
||||||
context.distance = { total: distance, units: null };
|
context.distance = { total: distance, units: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
#getRangeLabel(distance, settings) {
|
|
||||||
if (distance <= settings.melee) {
|
|
||||||
return game.i18n.localize('DAGGERHEART.Range.melee.name');
|
|
||||||
}
|
|
||||||
if (distance <= settings.veryClose) {
|
|
||||||
return game.i18n.localize('DAGGERHEART.Range.veryClose.name');
|
|
||||||
}
|
|
||||||
if (distance <= settings.close) {
|
|
||||||
return game.i18n.localize('DAGGERHEART.Range.close.name');
|
|
||||||
}
|
|
||||||
if (distance <= settings.far) {
|
|
||||||
return game.i18n.localize('DAGGERHEART.Range.far.name');
|
|
||||||
}
|
|
||||||
if (distance <= settings.veryFar) {
|
|
||||||
return game.i18n.localize('DAGGERHEART.Range.veryFar.name');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue