mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-18 16:09:03 +01:00
Merge branch 'main' into feature/death-moves
This commit is contained in:
commit
3447afc213
22 changed files with 265 additions and 85 deletions
|
|
@ -123,7 +123,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
context.formula = this.roll.constructFormula(this.config);
|
||||
if (this.actor?.system?.traits) context.abilities = this.getTraitModifiers();
|
||||
|
||||
context.showReaction = !this.config.roll?.type && context.rollType === 'DualityRoll';
|
||||
context.showReaction = !this.config.roll?.type || context.rollType === 'DualityRoll';
|
||||
context.reactionOverride = this.reactionOverride;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export default class DaggerheartMenu extends HandlebarsApplicationMixin(Abstract
|
|||
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ['dh-style'],
|
||||
classes: ['dh-style', 'directory'],
|
||||
window: {
|
||||
title: 'SIDEBAR.TabSettings'
|
||||
},
|
||||
|
|
|
|||
|
|
@ -96,6 +96,19 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
super.close(options);
|
||||
}
|
||||
|
||||
/** Ensure the chat theme inherits the interface theme */
|
||||
_replaceHTML(result, content, options) {
|
||||
const themedElement = result.log?.querySelector(".chat-log");
|
||||
themedElement?.classList.remove("themed", "theme-light", "theme-dark");
|
||||
super._replaceHTML(result, content, options);
|
||||
}
|
||||
|
||||
/** Remove chat log theme from notifications area */
|
||||
async _onFirstRender(result, content) {
|
||||
await super._onFirstRender(result, content);
|
||||
document.querySelector("#chat-notifications .chat-log")?.classList.remove("themed", "theme-light", "theme-dark")
|
||||
}
|
||||
|
||||
async onRollSimple(event, message) {
|
||||
const buttonType = event.target.dataset.type ?? 'damage',
|
||||
total = message.rolls.reduce((a, c) => a + Roll.fromJSON(c).total, 0),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
export { default as DhCombat } from './combat.mjs';
|
||||
export { default as DhCombatant } from './combatant.mjs';
|
||||
export { default as DhTagTeamRoll } from './tagTeamRoll.mjs';
|
||||
export { default as RegisteredTriggers } from './registeredTriggers.mjs';
|
||||
|
||||
export * as countdowns from './countdowns.mjs';
|
||||
export * as actions from './action/_module.mjs';
|
||||
|
|
|
|||
|
|
@ -164,26 +164,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
|
|||
|
||||
prepareBaseData() {
|
||||
super.prepareBaseData();
|
||||
|
||||
for (const action of this.actions ?? []) {
|
||||
if (!action.actor) continue;
|
||||
|
||||
const actionsToRegister = [];
|
||||
for (let i = 0; i < action.triggers.length; i++) {
|
||||
const trigger = action.triggers[i];
|
||||
const { args } = CONFIG.DH.TRIGGER.triggers[trigger.trigger];
|
||||
const fn = new foundry.utils.AsyncFunction(...args, `{${trigger.command}\n}`);
|
||||
actionsToRegister.push(fn.bind(action));
|
||||
if (i === action.triggers.length - 1)
|
||||
game.system.registeredTriggers.registerTriggers(
|
||||
trigger.trigger,
|
||||
action.actor?.uuid,
|
||||
trigger.triggeringActorType,
|
||||
this.parent.uuid,
|
||||
actionsToRegister
|
||||
);
|
||||
}
|
||||
}
|
||||
game.system.registeredTriggers.registerItemTriggers(this.parent);
|
||||
}
|
||||
|
||||
async _preCreate(data, options, user) {
|
||||
|
|
@ -246,6 +227,28 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
|
|||
const armorData = getScrollTextData(this.parent.parent.system.resources, changed.system.marks, 'armor');
|
||||
options.scrollingTextData = [armorData];
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
game.system.registeredTriggers.unregisterTriggers(triggersToRemove, this.parent.uuid);
|
||||
|
||||
if (!(this.parent.parent.token instanceof game.system.api.documents.DhToken)) {
|
||||
for (const token of this.parent.parent.getActiveTokens()) {
|
||||
game.system.registeredTriggers.unregisterTriggers(
|
||||
triggersToRemove,
|
||||
`${token.document.uuid}.${this.parent.uuid}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_onUpdate(changed, options, userId) {
|
||||
|
|
|
|||
154
module/data/registeredTriggers.mjs
Normal file
154
module/data/registeredTriggers.mjs
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
export default class RegisteredTriggers extends Map {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
registerTriggers(triggers, actor, uuid) {
|
||||
for (const triggerKey of Object.keys(CONFIG.DH.TRIGGER.triggers)) {
|
||||
const match = triggers[triggerKey];
|
||||
const existingTrigger = this.get(triggerKey);
|
||||
|
||||
if (!match) {
|
||||
if (existingTrigger?.get(uuid)) this.get(triggerKey).delete(uuid);
|
||||
} else {
|
||||
const { trigger, triggeringActorType, commands } = match;
|
||||
|
||||
if (!existingTrigger) this.set(trigger, new Map());
|
||||
this.get(trigger).set(uuid, { actor, triggeringActorType, commands });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerItemTriggers(item, registerOverride) {
|
||||
for (const action of item.system.actions ?? []) {
|
||||
if (!action.actor) continue;
|
||||
|
||||
/* Non actor-linked should only prep synthetic actors so they're not registering triggers unless they're on the canvas */
|
||||
if (
|
||||
!registerOverride &&
|
||||
!action.actor.prototypeToken.actorLink &&
|
||||
(!(action.actor.parent instanceof game.system.api.documents.DhToken) || !action.actor.parent?.uuid)
|
||||
)
|
||||
continue;
|
||||
|
||||
const triggers = {};
|
||||
for (const trigger of action.triggers) {
|
||||
const { args } = CONFIG.DH.TRIGGER.triggers[trigger.trigger];
|
||||
const fn = new foundry.utils.AsyncFunction(...args, `{${trigger.command}\n}`);
|
||||
|
||||
if (!triggers[trigger.trigger])
|
||||
triggers[trigger.trigger] = {
|
||||
trigger: trigger.trigger,
|
||||
triggeringActorType: trigger.triggeringActorType,
|
||||
commands: []
|
||||
};
|
||||
triggers[trigger.trigger].commands.push(fn.bind(action));
|
||||
}
|
||||
|
||||
this.registerTriggers(triggers, action.actor?.uuid, item.uuid);
|
||||
}
|
||||
}
|
||||
|
||||
unregisterTriggers(triggerKeys, uuid) {
|
||||
for (const triggerKey of triggerKeys) {
|
||||
const existingTrigger = this.get(triggerKey);
|
||||
if (!existingTrigger) return;
|
||||
|
||||
existingTrigger.delete(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
unregisterItemTriggers(items) {
|
||||
for (const item of items) {
|
||||
if (!item.system.actions.size) continue;
|
||||
|
||||
const triggers = (item.system.actions ?? []).reduce((acc, action) => {
|
||||
acc.push(...action.triggers.map(x => x.trigger));
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
this.unregisterTriggers(triggers, item.uuid);
|
||||
}
|
||||
}
|
||||
|
||||
unregisterSceneTriggers(scene) {
|
||||
for (const triggerKey of Object.keys(CONFIG.DH.TRIGGER.triggers)) {
|
||||
const existingTrigger = this.get(triggerKey);
|
||||
if (!existingTrigger) continue;
|
||||
const filtered = new Map();
|
||||
for (const [uuid, data] of existingTrigger.entries()) {
|
||||
if (!uuid.startsWith(scene.uuid)) filtered.set(uuid, data);
|
||||
}
|
||||
this.set(triggerKey, filtered);
|
||||
}
|
||||
}
|
||||
|
||||
registerSceneTriggers(scene) {
|
||||
/* TODO: Finish sceneEnvironment registration and unreg */
|
||||
// const systemData = new game.system.api.data.scenes.DHScene(scene.flags.daggerheart);
|
||||
// for (const environment of systemData.sceneEnvironments) {
|
||||
// for (const feature of environment.system.features) {
|
||||
// if(feature) this.registerItemTriggers(feature, true);
|
||||
// }
|
||||
// }
|
||||
|
||||
for (const actor of scene.tokens.filter(x => x.actor).map(x => x.actor)) {
|
||||
if (actor.prototypeToken.actorLink) continue;
|
||||
|
||||
for (const item of actor.items) {
|
||||
this.registerItemTriggers(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async runTrigger(trigger, currentActor, ...args) {
|
||||
const updates = [];
|
||||
const triggerSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).triggers;
|
||||
if (!triggerSettings.enabled) return updates;
|
||||
|
||||
const dualityTrigger = this.get(trigger);
|
||||
if (dualityTrigger) {
|
||||
const tokenBoundActors = ['adversary', 'environment'];
|
||||
const triggerActors = ['character', ...tokenBoundActors];
|
||||
for (let [itemUuid, { actor: actorUuid, triggeringActorType, commands }] of dualityTrigger.entries()) {
|
||||
const actor = await foundry.utils.fromUuid(actorUuid);
|
||||
if (!actor || !triggerActors.includes(actor.type)) continue;
|
||||
if (tokenBoundActors.includes(actor.type) && !actor.getActiveTokens().length) continue;
|
||||
|
||||
const triggerData = CONFIG.DH.TRIGGER.triggers[trigger];
|
||||
if (triggerData.usesActor && triggeringActorType !== 'any') {
|
||||
if (triggeringActorType === 'self' && currentActor?.uuid !== actorUuid) continue;
|
||||
else if (triggeringActorType === 'other' && currentActor?.uuid === actorUuid) continue;
|
||||
}
|
||||
|
||||
for (const command of commands) {
|
||||
try {
|
||||
if (CONFIG.debug.triggers) {
|
||||
const item = await foundry.utils.fromUuid(itemUuid);
|
||||
console.log(
|
||||
game.i18n.format('DAGGERHEART.UI.ConsoleLogs.triggerRun', {
|
||||
actor: actor.name ?? '<Missing Actor>',
|
||||
item: item?.name ?? '<Missing Item>',
|
||||
trigger: game.i18n.localize(triggerData.label)
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const result = await command(...args);
|
||||
if (result?.updates?.length) updates.push(...result.updates);
|
||||
} catch (_) {
|
||||
const triggerName = game.i18n.localize(triggerData.label);
|
||||
ui.notifications.error(
|
||||
game.i18n.format('DAGGERHEART.CONFIG.Triggers.triggerError', {
|
||||
trigger: triggerName,
|
||||
actor: currentActor?.name
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updates;
|
||||
}
|
||||
}
|
||||
|
|
@ -104,6 +104,16 @@ export default class DhpActor extends Actor {
|
|||
}
|
||||
}
|
||||
|
||||
async _preDelete() {
|
||||
if (this.prototypeToken.actorLink) {
|
||||
game.system.registeredTriggers.unregisterItemTriggers(this.items);
|
||||
} else {
|
||||
for (const token of this.getActiveTokens()) {
|
||||
game.system.registeredTriggers.unregisterItemTriggers(token.actor.items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_onDelete(options, userId) {
|
||||
super._onDelete(options, userId);
|
||||
for (const party of this.parties) {
|
||||
|
|
|
|||
|
|
@ -208,4 +208,23 @@ export default class DHItem extends foundry.documents.Item {
|
|||
|
||||
cls.create(msg);
|
||||
}
|
||||
|
||||
deleteTriggers() {
|
||||
const actions = Array.from(this.system.actions ?? []);
|
||||
if (!actions.length) return;
|
||||
|
||||
const triggerKeys = actions.flatMap(action => action.triggers.map(x => x.trigger));
|
||||
|
||||
game.system.registeredTriggers.unregisterTriggers(triggerKeys, this.uuid);
|
||||
|
||||
if (!(this.actor.parent instanceof game.system.api.documents.DhToken)) {
|
||||
for (const token of this.actor.getActiveTokens()) {
|
||||
game.system.registeredTriggers.unregisterTriggers(triggerKeys, `${token.document.uuid}.${this.uuid}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async _preDelete() {
|
||||
this.deleteTriggers();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -536,4 +536,10 @@ export default class DHToken extends CONFIG.Token.documentClass {
|
|||
};
|
||||
}
|
||||
//#endregion
|
||||
|
||||
async _preDelete() {
|
||||
if (this.actor && !this.actor.prototypeToken?.actorLink) {
|
||||
game.system.registeredTriggers.unregisterItemTriggers(this.actor.items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue