daggerheart/daggerheart.mjs
WBHarry 9d76405221
File Structure Rework (#262)
* Restructured all the files

* Moved build/daggerheart.js to ./daggerheart.js. Changed rollup to use the css file instead of the less

* Restored build/ folder

* Mvoed config out form under application

* Moved roll.mjs to module/dice and renamed to dhRolls.mjs

* Update module/canvas/placeables/_module.mjs

Co-authored-by: joaquinpereyra98 <24190917+joaquinpereyra98@users.noreply.github.com>

* Le massive export update

* Removed unncessary import

---------

Co-authored-by: joaquinpereyra98 <24190917+joaquinpereyra98@users.noreply.github.com>
2025-07-05 00:26:33 +02:00

266 lines
10 KiB
JavaScript

import { SYSTEM } from './module/config/system.mjs';
import * as applications from './module/applications/_module.mjs';
import * as models from './module/data/_module.mjs';
import * as documents from './module/documents/_module.mjs';
import RegisterHandlebarsHelpers from './module/helpers/handlebarsHelper.mjs';
import { DhDualityRollEnricher, DhTemplateEnricher } from './module/enrichers/_module.mjs';
import { getCommandTarget, rollCommandToJSON } from './module/helpers/utils.mjs';
import { NarrativeCountdowns, registerCountdownApplicationHooks } from './module/applications/ui/countdowns.mjs';
import { DualityRollColor } from './module/data/settings/Appearance.mjs';
import { DHRoll, DualityRoll, D20Roll, DamageRoll, DualityDie } from './module/dice/_module.mjs';
import { renderDualityButton } from './module/enrichers/DualityRollEnricher.mjs';
import { renderMeasuredTemplate } from './module/enrichers/TemplateEnricher.mjs';
import { registerCountdownHooks } from './module/data/countdowns.mjs';
import {
handlebarsRegistration,
settingsRegistration,
socketRegistration
} from './module/systemRegistration/_module.mjs';
import { placeables } from './module/canvas/_module.mjs';
Hooks.once('init', () => {
CONFIG.DH = SYSTEM;
game.system.api = {
applications,
models,
documents
};
CONFIG.TextEditor.enrichers.push(
...[
{
pattern: /\[\[\/dr\s?(.*?)\]\]/g,
enricher: DhDualityRollEnricher
},
{
pattern: /^@Template\[(.*)\]$/g,
enricher: DhTemplateEnricher
}
]
);
CONFIG.statusEffects = Object.values(SYSTEM.GENERAL.conditions).map(x => ({
...x,
name: game.i18n.localize(x.name)
}));
CONFIG.Dice.daggerheart = {
DualityDie: DualityDie,
DHRoll: DHRoll,
DualityRoll: DualityRoll,
D20Roll: D20Roll,
DamageRoll: DamageRoll
};
CONFIG.Dice.rolls = [...CONFIG.Dice.rolls, ...[DHRoll, DualityRoll, D20Roll, DamageRoll]];
CONFIG.MeasuredTemplate.objectClass = placeables.DhMeasuredTemplate;
CONFIG.Item.documentClass = documents.DHItem;
//Registering the Item DataModel
CONFIG.Item.dataModels = models.items.config;
const { Items, Actors } = foundry.documents.collections;
Items.unregisterSheet('core', foundry.applications.sheets.ItemSheetV2);
Items.registerSheet(SYSTEM.id, applications.sheets.items.Ancestry, { types: ['ancestry'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.sheets.items.Community, { types: ['community'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.sheets.items.Class, { types: ['class'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.sheets.items.Subclass, { types: ['subclass'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.sheets.items.Feature, { types: ['feature'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.sheets.items.DomainCard, { types: ['domainCard'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.sheets.items.Miscellaneous, {
types: ['miscellaneous'],
makeDefault: true
});
Items.registerSheet(SYSTEM.id, applications.sheets.items.Consumable, { types: ['consumable'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.sheets.items.Weapon, { types: ['weapon'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.sheets.items.Armor, { types: ['armor'], makeDefault: true });
Items.registerSheet(SYSTEM.id, applications.sheets.items.Beastform, { types: ['beastform'], makeDefault: true });
CONFIG.Actor.documentClass = documents.DhpActor;
CONFIG.Actor.dataModels = models.actors.config;
Actors.unregisterSheet('core', foundry.applications.sheets.ActorSheetV2);
Actors.registerSheet(SYSTEM.id, applications.sheets.actors.Character, { types: ['character'], makeDefault: true });
Actors.registerSheet(SYSTEM.id, applications.sheets.actors.Companion, { types: ['companion'], makeDefault: true });
Actors.registerSheet(SYSTEM.id, applications.sheets.actors.Adversary, { types: ['adversary'], makeDefault: true });
Actors.registerSheet(SYSTEM.id, applications.sheets.actors.Environment, {
types: ['environment'],
makeDefault: true
});
CONFIG.ActiveEffect.documentClass = documents.DhActiveEffect;
CONFIG.ActiveEffect.dataModels = models.activeEffects.config;
foundry.applications.apps.DocumentSheetConfig.unregisterSheet(
CONFIG.ActiveEffect.documentClass,
'core',
foundry.applications.sheets.ActiveEffectConfig
);
foundry.applications.apps.DocumentSheetConfig.registerSheet(
CONFIG.ActiveEffect.documentClass,
SYSTEM.id,
applications.sheetConfigs.ActiveEffectConfig,
{
makeDefault: true
}
);
CONFIG.Combat.dataModels = {
base: models.DhCombat
};
CONFIG.Combatant.dataModels = {
base: models.DhCombatant
};
CONFIG.ChatMessage.dataModels = models.chatMessages.config;
CONFIG.ChatMessage.documentClass = documents.DhChatMessage;
CONFIG.Canvas.rulerClass = placeables.DhRuler;
CONFIG.Combat.documentClass = documents.DhpCombat;
CONFIG.ui.combat = applications.ui.DhCombatTracker;
CONFIG.ui.chat = applications.ui.DhChatLog;
CONFIG.Token.rulerClass = placeables.DhTokenRuler;
CONFIG.ui.resources = applications.ui.DhFearTracker;
CONFIG.ux.ContextMenu = applications.ux.ContextMenu;
CONFIG.ux.TooltipManager = documents.DhTooltipManager;
game.socket.on(`system.${SYSTEM.id}`, socketRegistration.handleSocketEvent);
// Make Compendium Dialog resizable
foundry.applications.sidebar.apps.Compendium.DEFAULT_OPTIONS.window.resizable = true;
settingsRegistration.registerDHSettings();
RegisterHandlebarsHelpers.registerHelpers();
return handlebarsRegistration();
});
Hooks.on('ready', () => {
ui.resources = new CONFIG.ui.resources();
if (game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.appearance).displayFear !== 'hide')
ui.resources.render({ force: true });
document.body.classList.toggle(
'theme-colorful',
game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.appearance).dualityColorScheme ===
DualityRollColor.colorful.value
);
registerCountdownHooks();
socketRegistration.registerSocketHooks();
registerCountdownApplicationHooks();
});
Hooks.once('dicesoniceready', () => {});
Hooks.on('renderChatMessageHTML', (_, element) => {
element
.querySelectorAll('.duality-roll-button')
.forEach(element => element.addEventListener('click', renderDualityButton));
element
.querySelectorAll('.measured-template-button')
.forEach(element => element.addEventListener('click', renderMeasuredTemplate));
});
Hooks.on('renderJournalEntryPageProseMirrorSheet', (_, element) => {
element
.querySelectorAll('.duality-roll-button')
.forEach(element => element.addEventListener('click', renderDualityButton));
element
.querySelectorAll('.measured-template-button')
.forEach(element => element.addEventListener('click', renderMeasuredTemplate));
});
Hooks.on('renderHandlebarsApplication', (_, element) => {
element
.querySelectorAll('.duality-roll-button')
.forEach(element => element.addEventListener('click', renderDualityButton));
element
.querySelectorAll('.measured-template-button')
.forEach(element => element.addEventListener('click', renderMeasuredTemplate));
});
Hooks.on('chatMessage', (_, message) => {
if (message.startsWith('/dr')) {
const rollCommand = rollCommandToJSON(message.replace(/\/dr\s?/, ''));
if (!rollCommand) {
ui.notifications.error(game.i18n.localize('DAGGERHEART.Notification.Error.DualityParsing'));
return false;
}
const traitValue = rollCommand.trait?.toLowerCase();
const advantageState = rollCommand.advantage ? true : rollCommand.disadvantage ? false : null;
// Target not required if an attribute is not used.
const target = traitValue ? getCommandTarget() : undefined;
if (target || !traitValue) {
new Promise(async (resolve, reject) => {
const trait = target ? target.system.traits[traitValue] : undefined;
if (traitValue && !trait) {
ui.notifications.error(game.i18n.localize('DAGGERHEART.Notification.Error.AttributeFaulty'));
reject();
return;
}
const title = traitValue
? game.i18n.format('DAGGERHEART.Chat.DualityRoll.AbilityCheckTitle', {
ability: game.i18n.localize(SYSTEM.ACTOR.abilities[traitValue].label)
})
: game.i18n.localize('DAGGERHEART.General.Duality');
const config = {
title: title,
roll: {
trait: traitValue
},
data: {
traits: {
[traitValue]: trait
}
},
source: target,
hasSave: false,
dialog: { configure: false },
evaluate: true,
advantage: rollCommand.advantage == true,
disadvantage: rollCommand.disadvantage == true
};
await CONFIG.Dice.daggerheart['DualityRoll'].build(config);
resolve();
});
}
return false;
}
});
Hooks.on('renderJournalDirectory', async (tab, html, _, options) => {
if (tab.id === 'journal') {
if (options.parts && !options.parts.includes('footer')) return;
const buttons = tab.element.querySelector('.directory-footer.action-buttons');
const title = game.i18n.format('DAGGERHEART.Countdown.Title', {
type: game.i18n.localize('DAGGERHEART.Countdown.Types.narrative')
});
buttons.insertAdjacentHTML(
'afterbegin',
`
<button id="narrative-countdown-button">
<i class="fa-solid fa-stopwatch"></i>
<span style="font-weight: 400; font-family: var(--font-sans);">${title}</span>
</button>`
);
buttons.querySelector('#narrative-countdown-button').onclick = async () => {
new NarrativeCountdowns().open();
};
}
});