diff --git a/.gitignore b/.gitignore index 443ad0ef..61c6b176 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,4 @@ node_modules /packs Build foundry -styles/daggerheart.css -daggerheart.js -daggerheart.js.map \ No newline at end of file +styles/daggerheart.css \ No newline at end of file diff --git a/daggerheart.mjs b/daggerheart.mjs index 528e50f8..81b404d5 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -7,7 +7,7 @@ import { DhDualityRollEnricher, DhTemplateEnricher } from './module/enrichers/_m 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/dhRolls.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'; @@ -16,7 +16,7 @@ import { settingsRegistration, socketRegistration } from './module/systemRegistration/_module.mjs'; -import { DhPlaceables } from './module/canvas/_module.mjs'; +import { placeables } from './module/canvas/_module.mjs'; Hooks.once('init', () => { CONFIG.DH = SYSTEM; @@ -53,7 +53,7 @@ Hooks.once('init', () => { }; CONFIG.Dice.rolls = [...CONFIG.Dice.rolls, ...[DHRoll, DualityRoll, D20Roll, DamageRoll]]; - CONFIG.MeasuredTemplate.objectClass = DhPlaceables.DhMeasuredTemplate; + CONFIG.MeasuredTemplate.objectClass = placeables.DhMeasuredTemplate; CONFIG.Item.documentClass = documents.DHItem; @@ -62,26 +62,32 @@ Hooks.once('init', () => { const { Items, Actors } = foundry.documents.collections; Items.unregisterSheet('core', foundry.applications.sheets.ItemSheetV2); - Items.registerSheet(SYSTEM.id, applications.DhpAncestry, { types: ['ancestry'], makeDefault: true }); - Items.registerSheet(SYSTEM.id, applications.DhpCommunity, { types: ['community'], makeDefault: true }); - Items.registerSheet(SYSTEM.id, applications.DhpClassSheet, { types: ['class'], makeDefault: true }); - Items.registerSheet(SYSTEM.id, applications.DhpSubclass, { types: ['subclass'], makeDefault: true }); - Items.registerSheet(SYSTEM.id, applications.DhpFeatureSheet, { types: ['feature'], makeDefault: true }); - Items.registerSheet(SYSTEM.id, applications.DhpDomainCardSheet, { types: ['domainCard'], makeDefault: true }); - Items.registerSheet(SYSTEM.id, applications.DhpMiscellaneous, { types: ['miscellaneous'], makeDefault: true }); - Items.registerSheet(SYSTEM.id, applications.DhpConsumable, { types: ['consumable'], makeDefault: true }); - Items.registerSheet(SYSTEM.id, applications.DhpWeapon, { types: ['weapon'], makeDefault: true }); - Items.registerSheet(SYSTEM.id, applications.DhpArmor, { types: ['armor'], makeDefault: true }); - Items.registerSheet(SYSTEM.id, applications.DhBeastform, { types: ['beastform'], makeDefault: true }); + 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.DhCharacterSheet, { types: ['character'], makeDefault: true }); - Actors.registerSheet(SYSTEM.id, applications.DhCompanionSheet, { types: ['companion'], makeDefault: true }); - Actors.registerSheet(SYSTEM.id, applications.DhpAdversarySheet, { types: ['adversary'], makeDefault: true }); - Actors.registerSheet(SYSTEM.id, applications.DhpEnvironment, { types: ['environment'], makeDefault: true }); + 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; @@ -94,7 +100,7 @@ Hooks.once('init', () => { foundry.applications.apps.DocumentSheetConfig.registerSheet( CONFIG.ActiveEffect.documentClass, SYSTEM.id, - applications.DhActiveEffectConfig, + applications.sheetConfigs.ActiveEffectConfig, { makeDefault: true } @@ -108,17 +114,17 @@ Hooks.once('init', () => { base: models.DhCombatant }; - CONFIG.ChatMessage.dataModels = models.messages.config; + CONFIG.ChatMessage.dataModels = models.chatMessages.config; CONFIG.ChatMessage.documentClass = documents.DhChatMessage; - CONFIG.Canvas.rulerClass = DhPlaceables.DhRuler; + 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 = DhPlaceables.DhTokenRuler; + CONFIG.Token.rulerClass = placeables.DhTokenRuler; CONFIG.ui.resources = applications.ui.DhFearTracker; - CONFIG.ux.ContextMenu = applications.DhContextMenu; + CONFIG.ux.ContextMenu = applications.ux.ContextMenu; CONFIG.ux.TooltipManager = documents.DhTooltipManager; game.socket.on(`system.${SYSTEM.id}`, socketRegistration.handleSocketEvent); @@ -204,7 +210,7 @@ Hooks.on('chatMessage', (_, message) => { const title = traitValue ? game.i18n.format('DAGGERHEART.Chat.DualityRoll.AbilityCheckTitle', { - ability: game.i18n.localize(applications.config.actorConfig.abilities[traitValue].label) + ability: game.i18n.localize(SYSTEM.ACTOR.abilities[traitValue].label) }) : game.i18n.localize('DAGGERHEART.General.Duality'); diff --git a/module/_module.mjs b/module/_module.mjs new file mode 100644 index 00000000..2e1d6fb4 --- /dev/null +++ b/module/_module.mjs @@ -0,0 +1,9 @@ +export * as applications from './applications/_module.mjs'; +export * as canvas from './canvas/_module.mjs'; +export * as config from './config/_module.mjs'; +export * as data from './data/_module.mjs'; +export * as dice from './dice/_module.mjs'; +export * as documents from './documents/_module.mjs'; +export * as enrichers from './enrichers/_module.mjs'; +export * as helpers from './helpers/_module.mjs'; +export * as systemRegistration from './systemRegistration/_module.mjs'; diff --git a/module/applications/_module.mjs b/module/applications/_module.mjs index 286ad8bf..82c2866c 100644 --- a/module/applications/_module.mjs +++ b/module/applications/_module.mjs @@ -1,22 +1,8 @@ -export { default as DhCharacterSheet } from './sheets/actors/character.mjs'; -export { default as DhpAdversarySheet } from './sheets/actors/adversary.mjs'; -export { default as DhCompanionSheet } from './sheets/actors/companion.mjs'; -export { default as DhpClassSheet } from './sheets/items/class.mjs'; -export { default as DhpSubclass } from './sheets/items/subclass.mjs'; -export { default as DhpFeatureSheet } from './sheets/items/feature.mjs'; -export { default as DhpDomainCardSheet } from './sheets/items/domainCard.mjs'; -export { default as DhpAncestry } from './sheets/items/ancestry.mjs'; -export { default as DhpCommunity } from './sheets/items/community.mjs'; -export { default as DhpMiscellaneous } from './sheets/items/miscellaneous.mjs'; -export { default as DhpConsumable } from './sheets/items/consumable.mjs'; -export { default as DhpWeapon } from './sheets/items/weapon.mjs'; -export { default as DhpArmor } from './sheets/items/armor.mjs'; -export { default as DhpEnvironment } from './sheets/actors/environment.mjs'; -export { default as DhActiveEffectConfig } from './sheets/activeEffectConfig.mjs'; -export { default as DhContextMenu } from './ux/contextMenu.mjs'; -export { default as DhBeastform } from './sheets/items/beastform.mjs'; - -export * as config from '../config/_module.mjs'; -export * as api from './sheets/api/_modules.mjs'; +export * as characterCreation from './characterCreation/_module.mjs'; +export * as dialogs from './dialogs/_module.mjs'; +export * as levelup from './levelup/_module.mjs'; +export * as settings from './settings/_module.mjs'; +export * as sheets from './sheets/_module.mjs'; +export * as sheetConfigs from './sheets-configs/_module.mjs'; export * as ui from './ui/_module.mjs'; export * as ux from './ux/_module.mjs'; diff --git a/module/applications/characterCreation/_module.mjs b/module/applications/characterCreation/_module.mjs new file mode 100644 index 00000000..f5642951 --- /dev/null +++ b/module/applications/characterCreation/_module.mjs @@ -0,0 +1 @@ +export { default as CharacterCreation } from './characterCreation.mjs'; diff --git a/module/applications/dialogs/_module.mjs b/module/applications/dialogs/_module.mjs new file mode 100644 index 00000000..82c6f17d --- /dev/null +++ b/module/applications/dialogs/_module.mjs @@ -0,0 +1,9 @@ +export { default as BeastformDialog } from './beastformDialog.mjs'; +export { default as costSelectionDialog } from './costSelectionDialog.mjs'; +export { default as d20RollDialog } from './d20RollDialog.mjs'; +export { default as DamageDialog } from './damageDialog.mjs'; +export { default as DamageReductionDialog } from './damageReductionDialog.mjs'; +export { default as DamageSelectionDialog } from './damageSelectionDialog.mjs'; +export { default as DeathMove } from './deathMove.mjs'; +export { default as Downtime } from './downtime.mjs'; +export { default as OwnershipSelection } from './ownershipSelection.mjs'; diff --git a/module/applications/dialogs/downtime.mjs b/module/applications/dialogs/downtime.mjs index a5da3ffb..fc6da253 100644 --- a/module/applications/dialogs/downtime.mjs +++ b/module/applications/dialogs/downtime.mjs @@ -1,5 +1,3 @@ -import { actionsTypes } from '../../data/_module.mjs'; - const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV2) { diff --git a/module/applications/levelup/_module.mjs b/module/applications/levelup/_module.mjs new file mode 100644 index 00000000..dd4135b4 --- /dev/null +++ b/module/applications/levelup/_module.mjs @@ -0,0 +1,3 @@ +export { default as CharacterLevelup } from './characterLevelup.mjs'; +export { default as CompanionLevelup } from './companionLevelup.mjs'; +export { default as Levelup } from './levelup.mjs'; diff --git a/module/applications/settings/_module.mjs b/module/applications/settings/_module.mjs index b5b5748d..de11242e 100644 --- a/module/applications/settings/_module.mjs +++ b/module/applications/settings/_module.mjs @@ -1,13 +1,5 @@ -import DhAppearanceSettings from './appearanceSettings.mjs'; -import DhAutomationSettings from './automationSettings.mjs'; -import DhHomebrewSettings from './homebrewSettings.mjs'; -import DhRangeMeasurementSettings from './rangeMeasurementSettings.mjs'; -import DhVariantRuleSettings from './variantRuleSettings.mjs'; - -export { - DhAppearanceSettings, - DhAutomationSettings, - DhHomebrewSettings, - DhRangeMeasurementSettings, - DhVariantRuleSettings -}; +export { default as DhAppearanceSettings } from './appearanceSettings.mjs'; +export { default as DhAutomationSettings } from './automationSettings.mjs'; +export { default as DhHomebrewSettings } from './homebrewSettings.mjs'; +export { default as DhRangeMeasurementSettings } from './rangeMeasurementSettings.mjs'; +export { default as DhVariantRuleSettings } from './variantRuleSettings.mjs'; diff --git a/module/applications/settings/components/settingsActionsView.mjs b/module/applications/settings/components/settingsActionsView.mjs index 7d103432..a905e824 100644 --- a/module/applications/settings/components/settingsActionsView.mjs +++ b/module/applications/settings/components/settingsActionsView.mjs @@ -1,5 +1,5 @@ -import { actionsTypes } from '../../../data/_module.mjs'; -import DHActionConfig from '../../../config/Action.mjs'; +import { actionsTypes } from '../../../data/action/_module.mjs'; +import DHActionConfig from '../../sheets-configs/action-config.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; diff --git a/module/applications/sheets-configs/_module.mjs b/module/applications/sheets-configs/_module.mjs new file mode 100644 index 00000000..e1ae8fe2 --- /dev/null +++ b/module/applications/sheets-configs/_module.mjs @@ -0,0 +1,5 @@ +export { default as ActionConfig } from './action-config.mjs'; +export { default as AdversarySettings } from './adversary-settings.mjs'; +export { default as CompanionSettings } from './companion-settings.mjs'; +export { default as EnvironmentSettings } from './environment-settings.mjs'; +export { default as ActiveEffectConfig } from './activeEffectConfig.mjs'; diff --git a/module/config/Action.mjs b/module/applications/sheets-configs/action-config.mjs similarity index 99% rename from module/config/Action.mjs rename to module/applications/sheets-configs/action-config.mjs index edb3f0d0..61ce3fd7 100644 --- a/module/config/Action.mjs +++ b/module/applications/sheets-configs/action-config.mjs @@ -1,4 +1,4 @@ -import DaggerheartSheet from '../applications/sheets/daggerheart-sheet.mjs'; +import DaggerheartSheet from '../sheets/daggerheart-sheet.mjs'; const { ApplicationV2 } = foundry.applications.api; export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) { diff --git a/module/applications/sheets/activeEffectConfig.mjs b/module/applications/sheets-configs/activeEffectConfig.mjs similarity index 100% rename from module/applications/sheets/activeEffectConfig.mjs rename to module/applications/sheets-configs/activeEffectConfig.mjs diff --git a/module/applications/sheets/applications/adversary-settings.mjs b/module/applications/sheets-configs/adversary-settings.mjs similarity index 97% rename from module/applications/sheets/applications/adversary-settings.mjs rename to module/applications/sheets-configs/adversary-settings.mjs index 826a738e..22ad4b18 100644 --- a/module/applications/sheets/applications/adversary-settings.mjs +++ b/module/applications/sheets-configs/adversary-settings.mjs @@ -1,6 +1,6 @@ -import DHActionConfig from '../../../config/Action.mjs'; -import DHBaseItemSheet from '../api/base-item.mjs'; -import { actionsTypes } from '../../../data/_module.mjs'; +import DHActionConfig from './action-config.mjs'; +import DHBaseItemSheet from '../sheets/api/base-item.mjs'; +import { actionsTypes } from '../../data/action/_module.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; diff --git a/module/applications/sheets/applications/companion-settings.mjs b/module/applications/sheets-configs/companion-settings.mjs similarity index 97% rename from module/applications/sheets/applications/companion-settings.mjs rename to module/applications/sheets-configs/companion-settings.mjs index ed096781..7f9d5423 100644 --- a/module/applications/sheets/applications/companion-settings.mjs +++ b/module/applications/sheets-configs/companion-settings.mjs @@ -1,5 +1,5 @@ -import { GMUpdateEvent, socketEvent } from '../../../systemRegistration/socket.mjs'; -import DhCompanionlevelUp from '../../levelup/companionLevelup.mjs'; +import { GMUpdateEvent, socketEvent } from '../../systemRegistration/socket.mjs'; +import DhCompanionlevelUp from '../levelup/companionLevelup.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; diff --git a/module/applications/sheets/applications/environment-settings.mjs b/module/applications/sheets-configs/environment-settings.mjs similarity index 97% rename from module/applications/sheets/applications/environment-settings.mjs rename to module/applications/sheets-configs/environment-settings.mjs index f7954954..5e0c5cda 100644 --- a/module/applications/sheets/applications/environment-settings.mjs +++ b/module/applications/sheets-configs/environment-settings.mjs @@ -1,6 +1,6 @@ -import DHActionConfig from '../../../config/Action.mjs'; -import DHBaseItemSheet from '../api/base-item.mjs'; -import { actionsTypes } from '../../../data/_module.mjs'; +import DHActionConfig from './action-config.mjs'; +import DHBaseItemSheet from '../sheets/api/base-item.mjs'; +import { actionsTypes } from '../../data/action/_module.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; diff --git a/module/applications/sheets/_module.mjs b/module/applications/sheets/_module.mjs new file mode 100644 index 00000000..c503e054 --- /dev/null +++ b/module/applications/sheets/_module.mjs @@ -0,0 +1,3 @@ +export * as actors from './actors/_module.mjs'; +export * as api from './api/_modules.mjs'; +export * as items from './items/_module.mjs'; diff --git a/module/applications/sheets/actors/_module.mjs b/module/applications/sheets/actors/_module.mjs new file mode 100644 index 00000000..9998733c --- /dev/null +++ b/module/applications/sheets/actors/_module.mjs @@ -0,0 +1,4 @@ +export { default as Adversary } from './adversary.mjs'; +export { default as Character } from './character.mjs'; +export { default as Companion } from './companion.mjs'; +export { default as Environment } from './environment.mjs'; diff --git a/module/applications/sheets/actors/adversary.mjs b/module/applications/sheets/actors/adversary.mjs index acc364bb..a48c1fa4 100644 --- a/module/applications/sheets/actors/adversary.mjs +++ b/module/applications/sheets/actors/adversary.mjs @@ -1,6 +1,6 @@ -import DHActionConfig from '../../../config/Action.mjs'; +import DHActionConfig from '../../sheets-configs/action-config.mjs'; import DaggerheartSheet from '../daggerheart-sheet.mjs'; -import DHAdversarySettings from '../applications/adversary-settings.mjs'; +import DHAdversarySettings from '../../sheets-configs/adversary-settings.mjs'; const { ActorSheetV2 } = foundry.applications.sheets; export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) { diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index c4896f28..5a443119 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -6,7 +6,7 @@ import { abilities } from '../../../config/actorConfig.mjs'; import DhCharacterlevelUp from '../../levelup/characterLevelup.mjs'; import DhCharacterCreation from '../../characterCreation/characterCreation.mjs'; import FilterMenu from '../../ux/filter-menu.mjs'; -import DHActionConfig from '../../../config/Action.mjs'; +import DHActionConfig from '../../sheets-configs/action-config.mjs'; const { ActorSheetV2 } = foundry.applications.sheets; const { TextEditor } = foundry.applications.ux; diff --git a/module/applications/sheets/actors/companion.mjs b/module/applications/sheets/actors/companion.mjs index 23ff42b3..bf8f2ec6 100644 --- a/module/applications/sheets/actors/companion.mjs +++ b/module/applications/sheets/actors/companion.mjs @@ -1,5 +1,5 @@ import DaggerheartSheet from '../daggerheart-sheet.mjs'; -import DHCompanionSettings from '../applications/companion-settings.mjs'; +import DHCompanionSettings from '../../sheets-configs/companion-settings.mjs'; const { ActorSheetV2 } = foundry.applications.sheets; export default class DhCompanionSheet extends DaggerheartSheet(ActorSheetV2) { diff --git a/module/applications/sheets/actors/environment.mjs b/module/applications/sheets/actors/environment.mjs index dc0da8e9..733e8e10 100644 --- a/module/applications/sheets/actors/environment.mjs +++ b/module/applications/sheets/actors/environment.mjs @@ -1,5 +1,5 @@ import DaggerheartSheet from '../daggerheart-sheet.mjs'; -import DHEnvironmentSettings from '../applications/environment-settings.mjs'; +import DHEnvironmentSettings from '../../sheets-configs/environment-settings.mjs'; const { ActorSheetV2 } = foundry.applications.sheets; export default class DhpEnvironment extends DaggerheartSheet(ActorSheetV2) { diff --git a/module/applications/sheets/api/base-item.mjs b/module/applications/sheets/api/base-item.mjs index b9db8f0e..47ba5188 100644 --- a/module/applications/sheets/api/base-item.mjs +++ b/module/applications/sheets/api/base-item.mjs @@ -1,6 +1,6 @@ import DHApplicationMixin from './application-mixin.mjs'; -import { actionsTypes } from '../../../data/_module.mjs'; -import DHActionConfig from '../../../config/Action.mjs'; +import DHActionConfig from '../../sheets-configs/action-config.mjs'; +import { actionsTypes } from '../../../data/action/_module.mjs'; const { ItemSheetV2 } = foundry.applications.sheets; diff --git a/module/applications/sheets/items/_module.mjs b/module/applications/sheets/items/_module.mjs new file mode 100644 index 00000000..84332f96 --- /dev/null +++ b/module/applications/sheets/items/_module.mjs @@ -0,0 +1,11 @@ +export { default as Ancestry } from './ancestry.mjs'; +export { default as Armor } from './armor.mjs'; +export { default as Beastform } from './beastform.mjs'; +export { default as Class } from './class.mjs'; +export { default as Community } from './community.mjs'; +export { default as Consumable } from './consumable.mjs'; +export { default as DomainCard } from './domainCard.mjs'; +export { default as Feature } from './feature.mjs'; +export { default as Miscellaneous } from './miscellaneous.mjs'; +export { default as Subclass } from './subclass.mjs'; +export { default as Weapon } from './weapon.mjs'; diff --git a/module/applications/sheets/items/class.mjs b/module/applications/sheets/items/class.mjs index 98af93ea..2ba17346 100644 --- a/module/applications/sheets/items/class.mjs +++ b/module/applications/sheets/items/class.mjs @@ -1,6 +1,6 @@ import DHBaseItemSheet from '../api/base-item.mjs'; -import { actionsTypes } from '../../../data/_module.mjs'; -import DHActionConfig from '../../../config/Action.mjs'; +import DHActionConfig from '../../sheets-configs/action-config.mjs'; +import { actionsTypes } from '../../../data/action/_module.mjs'; const { TextEditor } = foundry.applications.ux; diff --git a/module/applications/sheets/items/subclass.mjs b/module/applications/sheets/items/subclass.mjs index 9c17a7e0..3c70d84a 100644 --- a/module/applications/sheets/items/subclass.mjs +++ b/module/applications/sheets/items/subclass.mjs @@ -1,6 +1,6 @@ import DHBaseItemSheet from '../api/base-item.mjs'; -import { actionsTypes } from '../../../data/_module.mjs'; -import DHActionConfig from '../../../config/Action.mjs'; +import DHActionConfig from '../../sheets-configs/action-config.mjs'; +import { actionsTypes } from '../../../data/action/_module.mjs'; export default class SubclassSheet extends DHBaseItemSheet { /**@inheritdoc */ diff --git a/module/applications/ui/_module.mjs b/module/applications/ui/_module.mjs index ef55360e..f1c32840 100644 --- a/module/applications/ui/_module.mjs +++ b/module/applications/ui/_module.mjs @@ -1,6 +1,4 @@ -import { default as DhChatLog } from './chatLog.mjs'; -import { default as DhCombatTracker } from './combatTracker.mjs'; -import * as DhCountdowns from './countdowns.mjs'; -import { default as DhFearTracker } from './fearTracker.mjs'; - -export { DhChatLog, DhCombatTracker, DhCountdowns, DhFearTracker }; +export { default as DhChatLog } from './chatLog.mjs'; +export { default as DhCombatTracker } from './combatTracker.mjs'; +export * as DhCountdowns from './countdowns.mjs'; +export { default as DhFearTracker } from './fearTracker.mjs'; diff --git a/module/applications/ui/chatLog.mjs b/module/applications/ui/chatLog.mjs index 4ec54946..182a3539 100644 --- a/module/applications/ui/chatLog.mjs +++ b/module/applications/ui/chatLog.mjs @@ -1,5 +1,3 @@ -import { actionsTypes } from '../../data/_module.mjs'; - export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLog { constructor() { super(); @@ -260,10 +258,10 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo actionUseButton = async (_, message) => { const parent = await foundry.utils.fromUuid(message.system.actor); - const testAction = Object.values(message.system.moves)[0].actions[0]; - const cls = actionsTypes[testAction.type]; + const actionType = Object.values(message.system.moves)[0].actions[0]; + const cls = CONFIG.DH.ACTIONS.actionTypes[actionType.type]; const action = new cls( - { ...testAction, _id: foundry.utils.randomID(), name: game.i18n.localize(testAction.name) }, + { ...actionType, _id: foundry.utils.randomID(), name: game.i18n.localize(actionType.name) }, { parent: parent } ); diff --git a/module/applications/ux/_module.mjs b/module/applications/ux/_module.mjs index a16a4d6f..5ec0eecf 100644 --- a/module/applications/ux/_module.mjs +++ b/module/applications/ux/_module.mjs @@ -1 +1,2 @@ export { default as FilterMenu } from './filter-menu.mjs'; +export { default as ContextMenu } from './contextMenu.mjs'; diff --git a/module/canvas/_module.mjs b/module/canvas/_module.mjs index 996c28ff..6b8885f4 100644 --- a/module/canvas/_module.mjs +++ b/module/canvas/_module.mjs @@ -1,3 +1 @@ -import * as DhPlaceables from './placeables/_module.mjs'; - -export { DhPlaceables }; +export * as placeables from './placeables/_module.mjs'; diff --git a/module/config/_module.mjs b/module/config/_module.mjs index b8ac6feb..88003595 100644 --- a/module/config/_module.mjs +++ b/module/config/_module.mjs @@ -1,25 +1,10 @@ -import * as action from './Action.mjs'; -import * as actionConfig from './actionConfig.mjs'; -import * as actorConfig from './actorConfig.mjs'; -import * as domainConfig from './domainConfig.mjs'; -import * as effectConfig from './effectConfig.mjs'; -import * as flagsConfig from './flagsConfig.mjs'; -import * as generalConfig from './generalConfig.mjs'; -import * as hooksConfig from './hooksConfig.mjs'; -import * as itemConfig from './itemConfig.mjs'; -import * as settingsConfig from './settingsConfig.mjs'; -import * as systemConfig from './system.mjs'; - -export { - action, - actionConfig, - actorConfig, - domainConfig, - effectConfig, - flagsConfig, - generalConfig, - hooksConfig, - itemConfig, - settingsConfig, - systemConfig -}; +export * as actionConfig from './actionConfig.mjs'; +export * as actorConfig from './actorConfig.mjs'; +export * as domainConfig from './domainConfig.mjs'; +export * as effectConfig from './effectConfig.mjs'; +export * as flagsConfig from './flagsConfig.mjs'; +export * as generalConfig from './generalConfig.mjs'; +export * as hooksConfig from './hooksConfig.mjs'; +export * as itemConfig from './itemConfig.mjs'; +export * as settingsConfig from './settingsConfig.mjs'; +export * as systemConfig from './system.mjs'; diff --git a/module/data/_module.mjs b/module/data/_module.mjs index 45a1d558..cac02a4a 100644 --- a/module/data/_module.mjs +++ b/module/data/_module.mjs @@ -1,9 +1,9 @@ export { default as DhCombat } from './combat.mjs'; export { default as DhCombatant } from './combatant.mjs'; -export * as actors from './actor/_module.mjs'; -export * as items from './item/_module.mjs'; -export { actionsTypes } from './action/_module.mjs'; -export * as messages from './chat-message/_modules.mjs'; -export * as fields from './fields/_module.mjs'; +export * as actions from './action/_module.mjs'; export * as activeEffects from './activeEffect/_module.mjs'; +export * as actors from './actor/_module.mjs'; +export * as chatMessages from './chat-message/_modules.mjs'; +export * as fields from './fields/_module.mjs'; +export * as items from './item/_module.mjs'; diff --git a/module/data/action/_module.mjs b/module/data/action/_module.mjs index 09c027d1..bc2c16fd 100644 --- a/module/data/action/_module.mjs +++ b/module/data/action/_module.mjs @@ -1,25 +1,20 @@ -import { - DHAttackAction, - DHBaseAction, - DhBeastformAction, - DHDamageAction, - DHEffectAction, - DHHealingAction, - DHMacroAction, - // DHResourceAction, - // DHSpellCastAction, - DHSummonAction -} from './action.mjs'; +export * as ActionDice from './actionDice.mjs'; +import AttackAction from './attackAction.mjs'; +import BaseAction from './baseAction.mjs'; +import BeastformAction from './beastformAction.mjs'; +import DamageAction from './damageAction.mjs'; +import EffectAction from './effectAction.mjs'; +import HealingAction from './healingAction.mjs'; +import MacroAction from './macroAction.mjs'; +import SummonAction from './summonAction.mjs'; export const actionsTypes = { - base: DHBaseAction, - attack: DHAttackAction, - // spellcast: DHSpellCastAction, - // resource: DHResourceAction, - damage: DHDamageAction, - healing: DHHealingAction, - summon: DHSummonAction, - effect: DHEffectAction, - macro: DHMacroAction, - beastform: DhBeastformAction + base: BaseAction, + attack: AttackAction, + damage: DamageAction, + healing: HealingAction, + summon: SummonAction, + effect: EffectAction, + macro: MacroAction, + beastform: BeastformAction }; diff --git a/module/data/action/attackAction.mjs b/module/data/action/attackAction.mjs new file mode 100644 index 00000000..c7cc83ca --- /dev/null +++ b/module/data/action/attackAction.mjs @@ -0,0 +1,34 @@ +import { DHDamageData } from './actionDice.mjs'; +import DHDamageAction from './damageAction.mjs'; + +export default class DHAttackAction extends DHDamageAction { + static extraSchemas = [...super.extraSchemas, ...['roll', 'save']]; + + static getRollType(parent) { + return parent.type === 'weapon' ? 'weapon' : 'spellcast'; + } + + get chatTemplate() { + return 'systems/daggerheart/templates/ui/chat/duality-roll.hbs'; + } + + prepareData() { + super.prepareData(); + if (this.damage.includeBase && !!this.item?.system?.damage) { + const baseDamage = this.getParentDamage(); + this.damage.parts.unshift(new DHDamageData(baseDamage)); + } + } + + getParentDamage() { + return { + value: { + multiplier: 'prof', + dice: this.item?.system?.damage.dice, + bonus: this.item?.system?.damage.bonus ?? 0 + }, + type: this.item?.system?.damage.type, + base: true + }; + } +} diff --git a/module/data/action/action.mjs b/module/data/action/baseAction.mjs similarity index 72% rename from module/data/action/action.mjs rename to module/data/action/baseAction.mjs index 92cfa9b3..e752421c 100644 --- a/module/data/action/action.mjs +++ b/module/data/action/baseAction.mjs @@ -1,7 +1,6 @@ import { DHActionDiceData, DHActionRollData, DHDamageData, DHDamageField } from './actionDice.mjs'; import DhpActor from '../../documents/actor.mjs'; import D20RollDialog from '../../applications/dialogs/d20RollDialog.mjs'; -import BeastformDialog from '../../applications/dialogs/beastformDialog.mjs'; const fields = foundry.data.fields; @@ -21,7 +20,7 @@ const fields = foundry.data.fields; - Auto use action <= Into Roll */ -export class DHBaseAction extends foundry.abstract.DataModel { +export default class DHBaseAction extends foundry.abstract.DataModel { static extraSchemas = []; static defineSchema() { @@ -585,239 +584,3 @@ export class DHBaseAction extends foundry.abstract.DataModel { cls.create(msg.toObject()); } } - -export class DHDamageAction extends DHBaseAction { - static extraSchemas = ['damage', 'target', 'effects']; - - getFormulaValue(part, data) { - let formulaValue = part.value; - if (this.hasRoll && part.resultBased && data.system.roll.result.duality === -1) return part.valueAlt; - return formulaValue; - } - - async rollDamage(event, data) { - let formula = this.damage.parts.map(p => this.getFormulaValue(p, data).getFormula(this.actor)).join(' + '); - - if (!formula || formula == '') return; - let roll = { formula: formula, total: formula }, - bonusDamage = []; - - if (isNaN(formula)) formula = Roll.replaceFormulaData(formula, this.getRollData(data.system ?? data)); - - const config = { - title: game.i18n.format('DAGGERHEART.Chat.DamageRoll.Title', { damage: this.name }), - roll: { formula }, - targets: data.system?.targets.filter(t => t.hit) ?? data.targets, - hasSave: this.hasSave, - isCritical: data.system?.roll?.isCritical ?? false, - source: data.system?.source, - event - }; - if (this.hasSave) config.onSave = this.save.damageMod; - if (data.system) { - config.source.message = data._id; - config.directDamage = false; - } - - roll = CONFIG.Dice.daggerheart.DamageRoll.build(config); - } -} - -export class DHAttackAction extends DHDamageAction { - static extraSchemas = [...super.extraSchemas, ...['roll', 'save']]; - - static getRollType(parent) { - return parent.type === 'weapon' ? 'weapon' : 'spellcast'; - } - - get chatTemplate() { - return 'systems/daggerheart/templates/ui/chat/duality-roll.hbs'; - } - - prepareData() { - super.prepareData(); - if (this.damage.includeBase && !!this.item?.system?.damage) { - const baseDamage = this.getParentDamage(); - this.damage.parts.unshift(new DHDamageData(baseDamage)); - } - } - - getParentDamage() { - return { - value: { - multiplier: 'prof', - dice: this.item?.system?.damage.dice, - bonus: this.item?.system?.damage.bonus ?? 0 - }, - type: this.item?.system?.damage.type, - base: true - }; - } -} - -export class DHHealingAction extends DHBaseAction { - static extraSchemas = ['target', 'effects', 'healing', 'roll']; - - static getRollType(parent) { - return 'spellcast'; - } - - getFormulaValue(data) { - let formulaValue = this.healing.value; - if (this.hasRoll && this.healing.resultBased && data.system.roll.result.duality === -1) - return this.healing.valueAlt; - return formulaValue; - } - - async rollHealing(event, data) { - let formulaValue = this.getFormulaValue(data), - formula = formulaValue.getFormula(this.actor); - - if (!formula || formula == '') return; - let roll = { formula: formula, total: formula }, - bonusDamage = []; - - const config = { - title: game.i18n.format('DAGGERHEART.Chat.HealingRoll.Title', { - healing: game.i18n.localize(CONFIG.DH.GENERAL.healingTypes[this.healing.type].label) - }), - roll: { formula }, - targets: (data.system?.targets ?? data.targets).filter(t => t.hit), - messageType: 'healing', - type: this.healing.type, - event - }; - - roll = CONFIG.Dice.daggerheart.DamageRoll.build(config); - } - - get chatTemplate() { - return 'systems/daggerheart/templates/ui/chat/healing-roll.hbs'; - } -} - -export class DHSummonAction extends DHBaseAction { - static defineSchema() { - return { - ...super.defineSchema(), - documentUUID: new fields.DocumentUUIDField({ type: 'Actor' }) - }; - } - - async trigger(event, ...args) { - if (!this.canSummon || !canvas.scene) return; - // const config = await super.use(event, args); - } - - get canSummon() { - return game.user.can('TOKEN_CREATE'); - } -} - -export class DHEffectAction extends DHBaseAction { - static extraSchemas = ['effects', 'target']; - - async use(event, ...args) { - const config = await super.use(event, args); - if (['error', 'warning'].includes(config.type)) return; - return await this.chatApplyEffects(event, config); - } - - async chatApplyEffects(event, data) { - const cls = getDocumentClass('ChatMessage'), - systemData = { - title: game.i18n.format('DAGGERHEART.Chat.ApplyEffect.Title', { name: this.name }), - origin: this.actor._id, - description: '', - targets: data.targets.map(x => ({ id: x.id, name: x.name, img: x.img, hit: true })), - action: { - itemId: this.item._id, - actionId: this._id - } - }, - msg = new cls({ - type: 'applyEffect', - user: game.user.id, - system: systemData, - content: await foundry.applications.handlebars.renderTemplate( - 'systems/daggerheart/templates/ui/chat/apply-effects.hbs', - systemData - ) - }); - - cls.create(msg.toObject()); - } - - get chatTemplate() { - return 'systems/daggerheart/templates/ui/chat/apply-effects.hbs'; - } -} - -export class DHMacroAction extends DHBaseAction { - static defineSchema() { - return { - ...super.defineSchema(), - documentUUID: new fields.DocumentUUIDField({ type: 'Macro' }) - }; - } - - async trigger(event, ...args) { - // const config = await super.use(event, args); - // if (['error', 'warning'].includes(config.type)) return; - const fixUUID = !this.documentUUID.includes('Macro.') ? `Macro.${this.documentUUID}` : this.documentUUID, - macro = await fromUuid(fixUUID); - try { - if (!macro) throw new Error(`No macro found for the UUID: ${this.documentUUID}.`); - macro.execute(); - } catch (error) { - ui.notifications.error(error); - } - } -} - -export class DhBeastformAction extends DHBaseAction { - static extraSchemas = ['beastform']; - - async use(event, ...args) { - const beastformConfig = this.prepareBeastformConfig(); - - const abort = await this.handleActiveTransformations(); - if (abort) return; - - const beastformUuid = await BeastformDialog.configure(beastformConfig); - if (!beastformUuid) return; - - await this.transform(beastformUuid); - } - - prepareBeastformConfig(config) { - const settingsTiers = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers; - const actorLevel = this.actor.system.levelData.level.current; - const actorTier = - Object.values(settingsTiers).find( - tier => actorLevel >= tier.levels.start && actorLevel <= tier.levels.end - ) ?? 1; - - return { - tierLimit: this.beastform.tierAccess.exact ?? actorTier - }; - } - - async transform(beastformUuid) { - const beastform = await foundry.utils.fromUuid(beastformUuid); - this.actor.createEmbeddedDocuments('Item', [beastform.toObject()]); - } - - async handleActiveTransformations() { - const beastformEffects = this.actor.effects.filter(x => x.type === 'beastform'); - if (beastformEffects.length > 0) { - for (let effect of beastformEffects) { - await effect.delete(); - } - - return true; - } - - return false; - } -} diff --git a/module/data/action/beastformAction.mjs b/module/data/action/beastformAction.mjs new file mode 100644 index 00000000..98d8053f --- /dev/null +++ b/module/data/action/beastformAction.mjs @@ -0,0 +1,49 @@ +import BeastformDialog from '../../applications/dialogs/beastformDialog.mjs'; +import DHBaseAction from './baseAction.mjs'; + +export default class DhBeastformAction extends DHBaseAction { + static extraSchemas = ['beastform']; + + async use(event, ...args) { + const beastformConfig = this.prepareBeastformConfig(); + + const abort = await this.handleActiveTransformations(); + if (abort) return; + + const beastformUuid = await BeastformDialog.configure(beastformConfig); + if (!beastformUuid) return; + + await this.transform(beastformUuid); + } + + prepareBeastformConfig(config) { + const settingsTiers = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers; + const actorLevel = this.actor.system.levelData.level.current; + const actorTier = + Object.values(settingsTiers).find( + tier => actorLevel >= tier.levels.start && actorLevel <= tier.levels.end + ) ?? 1; + + return { + tierLimit: this.beastform.tierAccess.exact ?? actorTier + }; + } + + async transform(beastformUuid) { + const beastform = await foundry.utils.fromUuid(beastformUuid); + this.actor.createEmbeddedDocuments('Item', [beastform.toObject()]); + } + + async handleActiveTransformations() { + const beastformEffects = this.actor.effects.filter(x => x.type === 'beastform'); + if (beastformEffects.length > 0) { + for (let effect of beastformEffects) { + await effect.delete(); + } + + return true; + } + + return false; + } +} diff --git a/module/data/action/damageAction.mjs b/module/data/action/damageAction.mjs new file mode 100644 index 00000000..ab34198d --- /dev/null +++ b/module/data/action/damageAction.mjs @@ -0,0 +1,38 @@ +import DHBaseAction from './baseAction.mjs'; + +export default class DHDamageAction extends DHBaseAction { + static extraSchemas = ['damage', 'target', 'effects']; + + getFormulaValue(part, data) { + let formulaValue = part.value; + if (this.hasRoll && part.resultBased && data.system.roll.result.duality === -1) return part.valueAlt; + return formulaValue; + } + + async rollDamage(event, data) { + let formula = this.damage.parts.map(p => this.getFormulaValue(p, data).getFormula(this.actor)).join(' + '); + + if (!formula || formula == '') return; + let roll = { formula: formula, total: formula }, + bonusDamage = []; + + if (isNaN(formula)) formula = Roll.replaceFormulaData(formula, this.getRollData(data.system ?? data)); + + const config = { + title: game.i18n.format('DAGGERHEART.Chat.DamageRoll.Title', { damage: this.name }), + roll: { formula }, + targets: data.system?.targets.filter(t => t.hit) ?? data.targets, + hasSave: this.hasSave, + isCritical: data.system?.roll?.isCritical ?? false, + source: data.system?.source, + event + }; + if (this.hasSave) config.onSave = this.save.damageMod; + if (data.system) { + config.source.message = data._id; + config.directDamage = false; + } + + roll = CONFIG.Dice.daggerheart.DamageRoll.build(config); + } +} diff --git a/module/data/action/effectAction.mjs b/module/data/action/effectAction.mjs new file mode 100644 index 00000000..6ef3e93c --- /dev/null +++ b/module/data/action/effectAction.mjs @@ -0,0 +1,40 @@ +import DHBaseAction from './baseAction.mjs'; + +export default class DHEffectAction extends DHBaseAction { + static extraSchemas = ['effects', 'target']; + + async use(event, ...args) { + const config = await super.use(event, args); + if (['error', 'warning'].includes(config.type)) return; + return await this.chatApplyEffects(event, config); + } + + async chatApplyEffects(event, data) { + const cls = getDocumentClass('ChatMessage'), + systemData = { + title: game.i18n.format('DAGGERHEART.Chat.ApplyEffect.Title', { name: this.name }), + origin: this.actor._id, + description: '', + targets: data.targets.map(x => ({ id: x.id, name: x.name, img: x.img, hit: true })), + action: { + itemId: this.item._id, + actionId: this._id + } + }, + msg = new cls({ + type: 'applyEffect', + user: game.user.id, + system: systemData, + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/ui/chat/apply-effects.hbs', + systemData + ) + }); + + cls.create(msg.toObject()); + } + + get chatTemplate() { + return 'systems/daggerheart/templates/ui/chat/apply-effects.hbs'; + } +} diff --git a/module/data/action/healingAction.mjs b/module/data/action/healingAction.mjs new file mode 100644 index 00000000..ed785388 --- /dev/null +++ b/module/data/action/healingAction.mjs @@ -0,0 +1,42 @@ +import DHBaseAction from './baseAction.mjs'; + +export default class DHHealingAction extends DHBaseAction { + static extraSchemas = ['target', 'effects', 'healing', 'roll']; + + static getRollType(parent) { + return 'spellcast'; + } + + getFormulaValue(data) { + let formulaValue = this.healing.value; + if (this.hasRoll && this.healing.resultBased && data.system.roll.result.duality === -1) + return this.healing.valueAlt; + return formulaValue; + } + + async rollHealing(event, data) { + let formulaValue = this.getFormulaValue(data), + formula = formulaValue.getFormula(this.actor); + + if (!formula || formula == '') return; + let roll = { formula: formula, total: formula }, + bonusDamage = []; + + const config = { + title: game.i18n.format('DAGGERHEART.Chat.HealingRoll.Title', { + healing: game.i18n.localize(CONFIG.DH.GENERAL.healingTypes[this.healing.type].label) + }), + roll: { formula }, + targets: (data.system?.targets ?? data.targets).filter(t => t.hit), + messageType: 'healing', + type: this.healing.type, + event + }; + + roll = CONFIG.Dice.daggerheart.DamageRoll.build(config); + } + + get chatTemplate() { + return 'systems/daggerheart/templates/ui/chat/healing-roll.hbs'; + } +} diff --git a/module/data/action/macroAction.mjs b/module/data/action/macroAction.mjs new file mode 100644 index 00000000..bfdc8f6b --- /dev/null +++ b/module/data/action/macroAction.mjs @@ -0,0 +1,24 @@ +import DHBaseAction from './baseAction.mjs'; + +export default class DHMacroAction extends DHBaseAction { + static defineSchema() { + const fields = foundry.data.fields; + return { + ...super.defineSchema(), + documentUUID: new fields.DocumentUUIDField({ type: 'Macro' }) + }; + } + + async trigger(event, ...args) { + // const config = await super.use(event, args); + // if (['error', 'warning'].includes(config.type)) return; + const fixUUID = !this.documentUUID.includes('Macro.') ? `Macro.${this.documentUUID}` : this.documentUUID, + macro = await fromUuid(fixUUID); + try { + if (!macro) throw new Error(`No macro found for the UUID: ${this.documentUUID}.`); + macro.execute(); + } catch (error) { + ui.notifications.error(error); + } + } +} diff --git a/module/data/action/summonAction.mjs b/module/data/action/summonAction.mjs new file mode 100644 index 00000000..13b4ee99 --- /dev/null +++ b/module/data/action/summonAction.mjs @@ -0,0 +1,20 @@ +import DHBaseAction from './baseAction.mjs'; + +export default class DHSummonAction extends DHBaseAction { + static defineSchema() { + const fields = foundry.data.fields; + return { + ...super.defineSchema(), + documentUUID: new fields.DocumentUUIDField({ type: 'Actor' }) + }; + } + + async trigger(event, ...args) { + if (!this.canSummon || !canvas.scene) return; + // const config = await super.use(event, args); + } + + get canSummon() { + return game.user.can('TOKEN_CREATE'); + } +} diff --git a/module/data/activeEffect/_module.mjs b/module/data/activeEffect/_module.mjs index f4627f0c..126aec5e 100644 --- a/module/data/activeEffect/_module.mjs +++ b/module/data/activeEffect/_module.mjs @@ -1,7 +1,7 @@ -import beastformEffect from './beastformEffect.mjs'; +import BeastformEffect from './beastformEffect.mjs'; -export { beastformEffect }; +export { BeastformEffect }; export const config = { - beastform: beastformEffect + beastform: BeastformEffect }; diff --git a/module/data/actor/environment.mjs b/module/data/actor/environment.mjs index d7a8b4b0..db75612b 100644 --- a/module/data/actor/environment.mjs +++ b/module/data/actor/environment.mjs @@ -1,4 +1,3 @@ -import { environmentTypes } from '../../config/actorConfig.mjs'; import BaseDataActor from './base.mjs'; import ActionField from '../fields/actionField.mjs'; import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs'; @@ -21,7 +20,7 @@ export default class DhEnvironment extends BaseDataActor { choices: CONFIG.DH.GENERAL.tiers, initial: CONFIG.DH.GENERAL.tiers.tier1.id }), - type: new fields.StringField({ choices: environmentTypes }), + type: new fields.StringField({ choices: CONFIG.DH.ACTOR.environmentTypes }), description: new fields.StringField(), impulses: new fields.StringField(), difficulty: new fields.NumberField({ required: true, initial: 11, integer: true }), diff --git a/module/data/chat-message/adversaryRoll.mjs b/module/data/chat-message/adversaryRoll.mjs index ea0f4678..9210ef99 100644 --- a/module/data/chat-message/adversaryRoll.mjs +++ b/module/data/chat-message/adversaryRoll.mjs @@ -1,4 +1,4 @@ -import { DHBaseAction } from '../action/action.mjs'; +import DHBaseAction from '../../data/action/baseAction.mjs'; const fields = foundry.data.fields; diff --git a/module/data/countdowns.mjs b/module/data/countdowns.mjs index fd26ebda..eaa8d9d9 100644 --- a/module/data/countdowns.mjs +++ b/module/data/countdowns.mjs @@ -1,4 +1,3 @@ -import { countdownTypes } from '../config/generalConfig.mjs'; import { RefreshType, socketEvent } from '../systemRegistration/socket.mjs'; export default class DhCountdowns extends foundry.abstract.DataModel { @@ -102,8 +101,8 @@ class DhCountdown extends foundry.abstract.DataModel { type: new fields.SchemaField({ value: new fields.StringField({ required: true, - choices: countdownTypes, - initial: countdownTypes.spotlight.id, + choices: CONFIG.DH.GENERAL.countdownTypes, + initial: CONFIG.DH.GENERAL.countdownTypes.spotlight.id, label: 'DAGGERHEART.Countdown.FIELDS.countdowns.element.progress.type.value.label' }), label: new fields.StringField({ diff --git a/module/data/fields/actionField.mjs b/module/data/fields/actionField.mjs index 3628bbae..da520fd1 100644 --- a/module/data/fields/actionField.mjs +++ b/module/data/fields/actionField.mjs @@ -1,9 +1,9 @@ -// import { actionsTypes } from '../action/_module.mjs'; +import { actionsTypes } from '../action/_module.mjs'; // Temporary Solution export default class ActionField extends foundry.data.fields.ObjectField { getModel(value) { - return game.system.api.models.actionsTypes[value.type] ?? game.system.api.models.actionsTypes.attack; + return actionsTypes[value.type] ?? actionsTypes.attack; } /* -------------------------------------------- */ diff --git a/module/data/item/weapon.mjs b/module/data/item/weapon.mjs index 07730711..30bed1e0 100644 --- a/module/data/item/weapon.mjs +++ b/module/data/item/weapon.mjs @@ -1,7 +1,5 @@ import BaseDataItem from './base.mjs'; import ActionField from '../fields/actionField.mjs'; -import { weaponFeatures } from '../../config/itemConfig.mjs'; -import { actionsTypes } from '../action/_module.mjs'; export default class DHWeapon extends BaseDataItem { /** @inheritDoc */ @@ -71,7 +69,7 @@ export default class DHWeapon extends BaseDataItem { } for (var feature of added) { - const featureData = weaponFeatures[feature.value]; + const featureData = CONFIG.DH.ITEM.weaponFeatures[feature.value]; if (featureData.effects?.length > 0) { const embeddedItems = await this.parent.createEmbeddedDocuments('ActiveEffect', [ { @@ -84,7 +82,7 @@ export default class DHWeapon extends BaseDataItem { } if (featureData.actions?.length > 0) { const newActions = featureData.actions.map(action => { - const cls = actionsTypes[action.type]; + const cls = CONFIG.DH.ACTIONS.actionsTypes[action.type]; return new cls( { ...action, _id: foundry.utils.randomID(), name: game.i18n.localize(action.name) }, { parent: this } diff --git a/module/data/settings/_module.mjs b/module/data/settings/_module.mjs index dc99ed36..032974a9 100644 --- a/module/data/settings/_module.mjs +++ b/module/data/settings/_module.mjs @@ -1,7 +1,5 @@ -import DhAppearance from './Appearance.mjs'; -import DhAutomation from './Automation.mjs'; -import DhHomebrew from './Homebrew.mjs'; -import DhRangeMeasurement from './RangeMeasurement.mjs'; -import DhVariantRules from './VariantRules.mjs'; - -export { DhAppearance, DhAutomation, DhHomebrew, DhRangeMeasurement, DhVariantRules }; +export { default as DhAppearance } from './Appearance.mjs'; +export { default as DhAutomation } from './Automation.mjs'; +export { default as DhHomebrew } from './Homebrew.mjs'; +export { default as DhRangeMeasurement } from './RangeMeasurement.mjs'; +export { default as DhVariantRules } from './VariantRules.mjs'; diff --git a/module/dice/_module.mjs b/module/dice/_module.mjs new file mode 100644 index 00000000..93c8c53a --- /dev/null +++ b/module/dice/_module.mjs @@ -0,0 +1,5 @@ +export { default as D20Roll } from './d20Roll.mjs'; +export { default as DamageRoll } from './damageRoll.mjs'; +export { default as DHRoll } from './dhRoll.mjs'; +export { default as DualityDie } from './dualityDie.mjs'; +export { default as DualityRoll } from './dualityRoll.mjs'; diff --git a/module/dice/d20Roll.mjs b/module/dice/d20Roll.mjs new file mode 100644 index 00000000..b36c0884 --- /dev/null +++ b/module/dice/d20Roll.mjs @@ -0,0 +1,179 @@ +import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs'; +import { setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs'; +import DHRoll from './dhRoll.mjs'; + +export default class D20Roll extends DHRoll { + constructor(formula, data = {}, options = {}) { + super(formula, data, options); + this.constructFormula(); + } + + static ADV_MODE = { + NORMAL: 0, + ADVANTAGE: 1, + DISADVANTAGE: -1 + }; + + static messageType = 'adversaryRoll'; + + static CRITICAL_TRESHOLD = 20; + + static DefaultDialog = D20RollDialog; + + get d20() { + if (!(this.terms[0] instanceof foundry.dice.terms.Die)) this.createBaseDice(); + return this.terms[0]; + } + + set d20(faces) { + if (!(this.terms[0] instanceof foundry.dice.terms.Die)) this.createBaseDice(); + this.terms[0].faces = this.getFaces(faces); + } + + get dAdvantage() { + return this.dice[2]; + } + + get isCritical() { + if (!this.d20._evaluated) return; + return this.d20.total >= this.constructor.CRITICAL_TRESHOLD; + } + + get hasAdvantage() { + return this.options.roll.advantage === this.constructor.ADV_MODE.ADVANTAGE; + } + + get hasDisadvantage() { + return this.options.roll.advantage === this.constructor.ADV_MODE.DISADVANTAGE; + } + + static applyKeybindings(config) { + let keys = { + normal: true, + advantage: false, + disadvantage: false + }; + + if (config.event) { + keys = { + normal: config.event.shiftKey || config.event.altKey || config.event.ctrlKey, + advantage: config.event.altKey, + disadvantage: config.event.ctrlKey + }; + } + + // Should the roll configuration dialog be displayed? + config.dialog.configure ??= !Object.values(keys).some(k => k); + + // Determine advantage mode + const advantage = config.roll.advantage === this.ADV_MODE.ADVANTAGE || keys.advantage || config.advantage; + const disadvantage = + config.roll.advantage === this.ADV_MODE.DISADVANTAGE || keys.disadvantage || config.disadvantage; + if (advantage && !disadvantage) config.roll.advantage = this.ADV_MODE.ADVANTAGE; + else if (!advantage && disadvantage) config.roll.advantage = this.ADV_MODE.DISADVANTAGE; + else config.roll.advantage = this.ADV_MODE.NORMAL; + } + + constructFormula(config) { + // this.terms = []; + this.createBaseDice(); + this.configureModifiers(); + this.resetFormula(); + return this._formula; + } + + createBaseDice() { + if (this.terms[0] instanceof foundry.dice.terms.Die) { + this.terms = [this.terms[0]]; + return; + } + this.terms[0] = new foundry.dice.terms.Die({ faces: 20 }); + } + + configureModifiers() { + this.applyAdvantage(); + this.applyBaseBonus(); + + this.options.experiences?.forEach(m => { + if (this.options.data.experiences?.[m]) + this.options.roll.modifiers.push({ + label: this.options.data.experiences[m].name, + value: this.options.data.experiences[m].total ?? this.options.data.experiences[m].value + }); + }); + + this.options.roll.modifiers?.forEach(m => { + this.terms.push(...this.formatModifier(m.value)); + }); + + this.baseTerms = foundry.utils.deepClone(this.terms); + + if (this.options.extraFormula) { + this.terms.push( + new foundry.dice.terms.OperatorTerm({ operator: '+' }), + ...this.constructor.parse(this.options.extraFormula, this.options.data) + ); + } + } + + applyAdvantage() { + this.d20.modifiers.findSplice(m => ['kh', 'kl'].includes(m)); + if (!this.hasAdvantage && !this.hasDisadvantage) this.number = 1; + else { + this.d20.number = 2; + this.d20.modifiers.push(this.hasAdvantage ? 'kh' : 'kl'); + } + } + + applyBaseBonus() { + this.options.roll.modifiers = []; + if (!this.options.roll.bonus) return; + this.options.roll.modifiers.push({ + label: 'Bonus to Hit', + value: this.options.roll.bonus + // value: Roll.replaceFormulaData('@attackBonus', this.data) + }); + } + + static async buildEvaluate(roll, config = {}, message = {}) { + if (config.evaluate !== false) await roll.evaluate(); + const advantageState = + config.roll.advantage == this.ADV_MODE.ADVANTAGE + ? true + : config.roll.advantage == this.ADV_MODE.DISADVANTAGE + ? false + : null; + setDiceSoNiceForDualityRoll(roll, advantageState); + this.postEvaluate(roll, config); + } + + static postEvaluate(roll, config = {}) { + super.postEvaluate(roll, config); + if (config.targets?.length) { + config.targets.forEach(target => { + const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion; + target.hit = this.isCritical || roll.total >= difficulty; + }); + } else if (config.roll.difficulty) + config.roll.success = roll.isCritical || roll.total >= config.roll.difficulty; + config.roll.advantage = { + type: config.roll.advantage, + dice: roll.dAdvantage?.denomination, + value: roll.dAdvantage?.total + }; + config.roll.isCritical = roll.isCritical; + config.roll.extra = roll.dice + .filter(d => !roll.baseTerms.includes(d)) + .map(d => { + return { + dice: d.denomination, + value: d.total + }; + }); + config.roll.modifierTotal = this.calculateTotalModifiers(roll); + } + + resetFormula() { + return (this._formula = this.constructor.getFormula(this.terms)); + } +} diff --git a/module/dice/damageRoll.mjs b/module/dice/damageRoll.mjs new file mode 100644 index 00000000..d9c4a61e --- /dev/null +++ b/module/dice/damageRoll.mjs @@ -0,0 +1,32 @@ +import DamageDialog from '../applications/dialogs/damageDialog.mjs'; +import DHRoll from './dhRoll.mjs'; + +export default class DamageRoll extends DHRoll { + constructor(formula, data = {}, options = {}) { + super(formula, data, options); + } + + static messageType = 'damageRoll'; + + static DefaultDialog = DamageDialog; + + static async postEvaluate(roll, config = {}) { + super.postEvaluate(roll, config); + config.roll.type = config.type; + config.roll.modifierTotal = this.calculateTotalModifiers(roll); + if (config.source?.message) { + const chatMessage = ui.chat.collection.get(config.source.message); + chatMessage.update({ 'system.damage': config }); + } + } + + constructFormula(config) { + super.constructFormula(config); + if (config.isCritical) { + const tmpRoll = new Roll(this._formula)._evaluateSync({ maximize: true }), + criticalBonus = tmpRoll.total - this.constructor.calculateTotalModifiers(tmpRoll); + this.terms.push(...this.formatModifier(criticalBonus)); + } + return (this._formula = this.constructor.getFormula(this.terms)); + } +} diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs new file mode 100644 index 00000000..c461e14a --- /dev/null +++ b/module/dice/dhRoll.mjs @@ -0,0 +1,133 @@ +import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs'; + +export default class DHRoll extends Roll { + baseTerms = []; + constructor(formula, data, options) { + super(formula, data, options); + } + + static messageType = 'adversaryRoll'; + + static DefaultDialog = D20RollDialog; + + static async build(config = {}, message = {}) { + const roll = await this.buildConfigure(config, message); + if (!roll) return; + await this.buildEvaluate(roll, config, (message = {})); + await this.buildPost(roll, config, (message = {})); + return config; + } + + static async buildConfigure(config = {}, message = {}) { + config.hooks = [...(config.hooks ?? []), '']; + config.dialog ??= {}; + for (const hook of config.hooks) { + if (Hooks.call(`${CONFIG.DH.id}.preRoll${hook.capitalize()}`, config, message) === false) return null; + } + + this.applyKeybindings(config); + + let roll = new this(config.roll.formula, config.data, config); + if (config.dialog.configure !== false) { + // Open Roll Dialog + const DialogClass = config.dialog?.class ?? this.DefaultDialog; + const configDialog = await DialogClass.configure(roll, config, message); + if (!configDialog) return; + } + + for (const hook of config.hooks) { + if ( + Hooks.call(`${CONFIG.DH.id}.post${hook.capitalize()}RollConfiguration`, roll, config, message) === false + ) + return []; + } + return roll; + } + + static async buildEvaluate(roll, config = {}, message = {}) { + if (config.evaluate !== false) await roll.evaluate(); + this.postEvaluate(roll, config); + } + + static async buildPost(roll, config, message) { + for (const hook of config.hooks) { + if (Hooks.call(`${CONFIG.DH.id}.postRoll${hook.capitalize()}`, config, message) === false) return null; + } + + // Create Chat Message + if (config.source?.message) { + } else { + const messageData = {}; + config.message = await this.toMessage(roll, config); + } + } + + static postEvaluate(roll, config = {}) { + if (!config.roll) config.roll = {}; + config.roll.total = roll.total; + config.roll.formula = roll.formula; + config.roll.dice = []; + roll.dice.forEach(d => { + config.roll.dice.push({ + dice: d.denomination, + total: d.total, + formula: d.formula, + results: d.results + }); + }); + } + + static async toMessage(roll, config) { + const cls = getDocumentClass('ChatMessage'), + msg = { + type: this.messageType, + user: game.user.id, + sound: config.mute ? null : CONFIG.sounds.dice, + system: config, + rolls: [roll] + }; + return await cls.create(msg); + } + + static applyKeybindings(config) { + if (config.event) + config.dialog.configure ??= !(config.event.shiftKey || config.event.altKey || config.event.ctrlKey); + } + + formatModifier(modifier) { + const numTerm = modifier < 0 ? '-' : '+'; + return [ + new foundry.dice.terms.OperatorTerm({ operator: numTerm }), + new foundry.dice.terms.NumericTerm({ number: Math.abs(modifier) }) + ]; + } + + getFaces(faces) { + return Number(faces.startsWith('d') ? faces.replace('d', '') : faces); + } + + constructFormula(config) { + this.terms = Roll.parse(this.options.roll.formula, config.data); + + if (this.options.extraFormula) { + this.terms.push( + new foundry.dice.terms.OperatorTerm({ operator: '+' }), + ...this.constructor.parse(this.options.extraFormula, this.options.data) + ); + } + return (this._formula = this.constructor.getFormula(this.terms)); + } + + static calculateTotalModifiers(roll) { + let modifierTotal = 0; + for (let i = 0; i < roll.terms.length; i++) { + if ( + roll.terms[i] instanceof foundry.dice.terms.NumericTerm && + !!roll.terms[i - 1] && + roll.terms[i - 1] instanceof foundry.dice.terms.OperatorTerm + ) + modifierTotal += Number(`${roll.terms[i - 1].operator}${roll.terms[i].total}`); + } + return modifierTotal; + } +} diff --git a/module/dice/dhRolls.mjs b/module/dice/dhRolls.mjs deleted file mode 100644 index 460a4af7..00000000 --- a/module/dice/dhRolls.mjs +++ /dev/null @@ -1,493 +0,0 @@ -import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs'; -import DamageDialog from '../applications/dialogs/damageDialog.mjs'; -import { setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs'; - -/* - - Damage & other resources roll - - Close dialog => don't roll -*/ - -export class DHRoll extends Roll { - baseTerms = []; - constructor(formula, data, options) { - super(formula, data, options); - } - - static messageType = 'adversaryRoll'; - - static DefaultDialog = D20RollDialog; - - static async build(config = {}, message = {}) { - const roll = await this.buildConfigure(config, message); - if (!roll) return; - await this.buildEvaluate(roll, config, (message = {})); - await this.buildPost(roll, config, (message = {})); - return config; - } - - static async buildConfigure(config = {}, message = {}) { - config.hooks = [...(config.hooks ?? []), '']; - config.dialog ??= {}; - for (const hook of config.hooks) { - if (Hooks.call(`${CONFIG.DH.id}.preRoll${hook.capitalize()}`, config, message) === false) return null; - } - - this.applyKeybindings(config); - - let roll = new this(config.roll.formula, config.data, config); - if (config.dialog.configure !== false) { - // Open Roll Dialog - const DialogClass = config.dialog?.class ?? this.DefaultDialog; - const configDialog = await DialogClass.configure(roll, config, message); - if (!configDialog) return; - } - - for (const hook of config.hooks) { - if ( - Hooks.call(`${CONFIG.DH.id}.post${hook.capitalize()}RollConfiguration`, roll, config, message) === false - ) - return []; - } - return roll; - } - - static async buildEvaluate(roll, config = {}, message = {}) { - if (config.evaluate !== false) await roll.evaluate(); - this.postEvaluate(roll, config); - } - - static async buildPost(roll, config, message) { - for (const hook of config.hooks) { - if (Hooks.call(`${CONFIG.DH.id}.postRoll${hook.capitalize()}`, config, message) === false) return null; - } - - // Create Chat Message - if (config.source?.message) { - } else { - const messageData = {}; - config.message = await this.toMessage(roll, config); - } - } - - static postEvaluate(roll, config = {}) { - if (!config.roll) config.roll = {}; - config.roll.total = roll.total; - config.roll.formula = roll.formula; - config.roll.dice = []; - roll.dice.forEach(d => { - config.roll.dice.push({ - dice: d.denomination, - total: d.total, - formula: d.formula, - results: d.results - }); - }); - } - - static async toMessage(roll, config) { - const cls = getDocumentClass('ChatMessage'), - msg = { - type: this.messageType, - user: game.user.id, - sound: config.mute ? null : CONFIG.sounds.dice, - system: config, - rolls: [roll] - }; - return await cls.create(msg); - } - - static applyKeybindings(config) { - if (config.event) - config.dialog.configure ??= !(config.event.shiftKey || config.event.altKey || config.event.ctrlKey); - } - - formatModifier(modifier) { - const numTerm = modifier < 0 ? '-' : '+'; - return [ - new foundry.dice.terms.OperatorTerm({ operator: numTerm }), - new foundry.dice.terms.NumericTerm({ number: Math.abs(modifier) }) - ]; - } - - getFaces(faces) { - return Number(faces.startsWith('d') ? faces.replace('d', '') : faces); - } - - constructFormula(config) { - this.terms = Roll.parse(this.options.roll.formula, config.data); - - if (this.options.extraFormula) { - this.terms.push( - new foundry.dice.terms.OperatorTerm({ operator: '+' }), - ...this.constructor.parse(this.options.extraFormula, this.options.data) - ); - } - return (this._formula = this.constructor.getFormula(this.terms)); - } - - static calculateTotalModifiers(roll) { - let modifierTotal = 0; - for (let i = 0; i < roll.terms.length; i++) { - if ( - roll.terms[i] instanceof foundry.dice.terms.NumericTerm && - !!roll.terms[i - 1] && - roll.terms[i - 1] instanceof foundry.dice.terms.OperatorTerm - ) - modifierTotal += Number(`${roll.terms[i - 1].operator}${roll.terms[i].total}`); - } - return modifierTotal; - } -} - -export class DualityDie extends foundry.dice.terms.Die { - constructor({ number = 1, faces = 12, ...args } = {}) { - super({ number, faces, ...args }); - } -} - -export class D20Roll extends DHRoll { - constructor(formula, data = {}, options = {}) { - super(formula, data, options); - this.constructFormula(); - } - - static ADV_MODE = { - NORMAL: 0, - ADVANTAGE: 1, - DISADVANTAGE: -1 - }; - - static messageType = 'adversaryRoll'; - - static CRITICAL_TRESHOLD = 20; - - static DefaultDialog = D20RollDialog; - - get d20() { - if (!(this.terms[0] instanceof foundry.dice.terms.Die)) this.createBaseDice(); - return this.terms[0]; - } - - set d20(faces) { - if (!(this.terms[0] instanceof foundry.dice.terms.Die)) this.createBaseDice(); - this.terms[0].faces = this.getFaces(faces); - } - - get dAdvantage() { - return this.dice[2]; - } - - get isCritical() { - if (!this.d20._evaluated) return; - return this.d20.total >= this.constructor.CRITICAL_TRESHOLD; - } - - get hasAdvantage() { - return this.options.roll.advantage === this.constructor.ADV_MODE.ADVANTAGE; - } - - get hasDisadvantage() { - return this.options.roll.advantage === this.constructor.ADV_MODE.DISADVANTAGE; - } - - static applyKeybindings(config) { - let keys = { - normal: true, - advantage: false, - disadvantage: false - }; - - if (config.event) { - keys = { - normal: config.event.shiftKey || config.event.altKey || config.event.ctrlKey, - advantage: config.event.altKey, - disadvantage: config.event.ctrlKey - }; - } - - // Should the roll configuration dialog be displayed? - config.dialog.configure ??= !Object.values(keys).some(k => k); - - // Determine advantage mode - const advantage = config.roll.advantage === this.ADV_MODE.ADVANTAGE || keys.advantage || config.advantage; - const disadvantage = - config.roll.advantage === this.ADV_MODE.DISADVANTAGE || keys.disadvantage || config.disadvantage; - if (advantage && !disadvantage) config.roll.advantage = this.ADV_MODE.ADVANTAGE; - else if (!advantage && disadvantage) config.roll.advantage = this.ADV_MODE.DISADVANTAGE; - else config.roll.advantage = this.ADV_MODE.NORMAL; - } - - constructFormula(config) { - // this.terms = []; - this.createBaseDice(); - this.configureModifiers(); - this.resetFormula(); - return this._formula; - } - - createBaseDice() { - if (this.terms[0] instanceof foundry.dice.terms.Die) { - this.terms = [this.terms[0]]; - return; - } - this.terms[0] = new foundry.dice.terms.Die({ faces: 20 }); - } - - configureModifiers() { - this.applyAdvantage(); - this.applyBaseBonus(); - - this.options.experiences?.forEach(m => { - if (this.options.data.experiences?.[m]) - this.options.roll.modifiers.push({ - label: this.options.data.experiences[m].name, - value: this.options.data.experiences[m].total ?? this.options.data.experiences[m].value - }); - }); - - this.options.roll.modifiers?.forEach(m => { - this.terms.push(...this.formatModifier(m.value)); - }); - - this.baseTerms = foundry.utils.deepClone(this.terms); - - if (this.options.extraFormula) { - this.terms.push( - new foundry.dice.terms.OperatorTerm({ operator: '+' }), - ...this.constructor.parse(this.options.extraFormula, this.options.data) - ); - } - } - - applyAdvantage() { - this.d20.modifiers.findSplice(m => ['kh', 'kl'].includes(m)); - if (!this.hasAdvantage && !this.hasDisadvantage) this.number = 1; - else { - this.d20.number = 2; - this.d20.modifiers.push(this.hasAdvantage ? 'kh' : 'kl'); - } - } - - applyBaseBonus() { - this.options.roll.modifiers = []; - if (!this.options.roll.bonus) return; - this.options.roll.modifiers.push({ - label: 'Bonus to Hit', - value: this.options.roll.bonus - // value: Roll.replaceFormulaData('@attackBonus', this.data) - }); - } - - static async buildEvaluate(roll, config = {}, message = {}) { - if (config.evaluate !== false) await roll.evaluate(); - const advantageState = - config.roll.advantage == this.ADV_MODE.ADVANTAGE - ? true - : config.roll.advantage == this.ADV_MODE.DISADVANTAGE - ? false - : null; - setDiceSoNiceForDualityRoll(roll, advantageState); - this.postEvaluate(roll, config); - } - - static postEvaluate(roll, config = {}) { - super.postEvaluate(roll, config); - if (config.targets?.length) { - config.targets.forEach(target => { - const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion; - target.hit = this.isCritical || roll.total >= difficulty; - }); - } else if (config.roll.difficulty) - config.roll.success = roll.isCritical || roll.total >= config.roll.difficulty; - config.roll.advantage = { - type: config.roll.advantage, - dice: roll.dAdvantage?.denomination, - value: roll.dAdvantage?.total - }; - config.roll.isCritical = roll.isCritical; - config.roll.extra = roll.dice - .filter(d => !roll.baseTerms.includes(d)) - .map(d => { - return { - dice: d.denomination, - value: d.total - }; - }); - config.roll.modifierTotal = this.calculateTotalModifiers(roll); - } - - resetFormula() { - return (this._formula = this.constructor.getFormula(this.terms)); - } -} - -export class DualityRoll extends D20Roll { - _advantageFaces = 6; - - constructor(formula, data = {}, options = {}) { - super(formula, data, options); - } - - static messageType = 'dualityRoll'; - - static DefaultDialog = D20RollDialog; - - get dHope() { - // if ( !(this.terms[0] instanceof foundry.dice.terms.Die) ) return; - if (!(this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie)) this.createBaseDice(); - return this.dice[0]; - // return this.#hopeDice; - } - - set dHope(faces) { - if (!(this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie)) this.createBaseDice(); - this.terms[0].faces = this.getFaces(faces); - // this.#hopeDice = `d${face}`; - } - - get dFear() { - // if ( !(this.terms[1] instanceof foundry.dice.terms.Die) ) return; - if (!(this.dice[1] instanceof CONFIG.Dice.daggerheart.DualityDie)) this.createBaseDice(); - return this.dice[1]; - // return this.#fearDice; - } - - set dFear(faces) { - if (!(this.dice[1] instanceof CONFIG.Dice.daggerheart.DualityDie)) this.createBaseDice(); - this.dice[1].faces = this.getFaces(faces); - // this.#fearDice = `d${face}`; - } - - get dAdvantage() { - return this.dice[2]; - } - - get advantageFaces() { - return this._advantageFaces; - } - - set advantageFaces(faces) { - this._advantageFaces = this.getFaces(faces); - } - - get isCritical() { - if (!this.dHope._evaluated || !this.dFear._evaluated) return; - return this.dHope.total === this.dFear.total; - } - - get withHope() { - if (!this._evaluated) return; - return this.dHope.total > this.dFear.total; - } - - get withFear() { - if (!this._evaluated) return; - return this.dHope.total < this.dFear.total; - } - - get hasBarRally() { - return null; - } - - get totalLabel() { - const label = this.withHope - ? 'DAGGERHEART.General.Hope' - : this.withFear - ? 'DAGGERHEART.General.Fear' - : 'DAGGERHEART.General.CriticalSuccess'; - - return game.i18n.localize(label); - } - - updateFormula() {} - - createBaseDice() { - if ( - this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie && - this.dice[1] instanceof CONFIG.Dice.daggerheart.DualityDie - ) { - this.terms = [this.terms[0], this.terms[1], this.terms[2]]; - return; - } - this.terms[0] = new CONFIG.Dice.daggerheart.DualityDie(); - this.terms[1] = new foundry.dice.terms.OperatorTerm({ operator: '+' }); - this.terms[2] = new CONFIG.Dice.daggerheart.DualityDie(); - } - - applyAdvantage() { - const dieFaces = this.advantageFaces, - bardRallyFaces = this.hasBarRally, - advDie = new foundry.dice.terms.Die({ faces: dieFaces }); - if (this.hasAdvantage || this.hasDisadvantage || bardRallyFaces) - this.terms.push(new foundry.dice.terms.OperatorTerm({ operator: this.hasDisadvantage ? '-' : '+' })); - if (bardRallyFaces) { - const rallyDie = new foundry.dice.terms.Die({ faces: bardRallyFaces }); - if (this.hasAdvantage) { - this.terms.push( - new foundry.dice.terms.PoolTerm({ - terms: [advDie.formula, rallyDie.formula], - modifiers: ['kh'] - }) - ); - } else if (this.hasDisadvantage) { - this.terms.push(advDie, new foundry.dice.terms.OperatorTerm({ operator: '+' }), rallyDie); - } - } else if (this.hasAdvantage || this.hasDisadvantage) this.terms.push(advDie); - } - - applyBaseBonus() { - this.options.roll.modifiers = []; - if (!this.options.roll.trait) return; - this.options.roll.modifiers.push({ - label: `DAGGERHEART.Abilities.${this.options.roll.trait}.name`, - value: Roll.replaceFormulaData(`@traits.${this.options.roll.trait}.total`, this.data) - }); - } - - static postEvaluate(roll, config = {}) { - super.postEvaluate(roll, config); - config.roll.hope = { - dice: roll.dHope.denomination, - value: roll.dHope.total - }; - config.roll.fear = { - dice: roll.dFear.denomination, - value: roll.dFear.total - }; - config.roll.result = { - duality: roll.withHope ? 1 : roll.withFear ? -1 : 0, - total: roll.dHope.total + roll.dFear.total, - label: roll.totalLabel - }; - } -} - -export class DamageRoll extends DHRoll { - constructor(formula, data = {}, options = {}) { - super(formula, data, options); - } - - static messageType = 'damageRoll'; - - static DefaultDialog = DamageDialog; - - static async postEvaluate(roll, config = {}) { - super.postEvaluate(roll, config); - config.roll.type = config.type; - config.roll.modifierTotal = this.calculateTotalModifiers(roll); - if (config.source?.message) { - const chatMessage = ui.chat.collection.get(config.source.message); - chatMessage.update({ 'system.damage': config }); - } - } - - constructFormula(config) { - super.constructFormula(config); - if (config.isCritical) { - const tmpRoll = new Roll(this._formula)._evaluateSync({ maximize: true }), - criticalBonus = tmpRoll.total - this.constructor.calculateTotalModifiers(tmpRoll); - this.terms.push(...this.formatModifier(criticalBonus)); - } - return (this._formula = this.constructor.getFormula(this.terms)); - } -} diff --git a/module/dice/dualityDie.mjs b/module/dice/dualityDie.mjs new file mode 100644 index 00000000..f8fa0410 --- /dev/null +++ b/module/dice/dualityDie.mjs @@ -0,0 +1,5 @@ +export default class DualityDie extends foundry.dice.terms.Die { + constructor({ number = 1, faces = 12, ...args } = {}) { + super({ number, faces, ...args }); + } +} diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs new file mode 100644 index 00000000..0960ba1b --- /dev/null +++ b/module/dice/dualityRoll.mjs @@ -0,0 +1,143 @@ +import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs'; +import D20Roll from './d20Roll.mjs'; + +export default class DualityRoll extends D20Roll { + _advantageFaces = 6; + + constructor(formula, data = {}, options = {}) { + super(formula, data, options); + } + + static messageType = 'dualityRoll'; + + static DefaultDialog = D20RollDialog; + + get dHope() { + // if ( !(this.terms[0] instanceof foundry.dice.terms.Die) ) return; + if (!(this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie)) this.createBaseDice(); + return this.dice[0]; + // return this.#hopeDice; + } + + set dHope(faces) { + if (!(this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie)) this.createBaseDice(); + this.terms[0].faces = this.getFaces(faces); + // this.#hopeDice = `d${face}`; + } + + get dFear() { + // if ( !(this.terms[1] instanceof foundry.dice.terms.Die) ) return; + if (!(this.dice[1] instanceof CONFIG.Dice.daggerheart.DualityDie)) this.createBaseDice(); + return this.dice[1]; + // return this.#fearDice; + } + + set dFear(faces) { + if (!(this.dice[1] instanceof CONFIG.Dice.daggerheart.DualityDie)) this.createBaseDice(); + this.dice[1].faces = this.getFaces(faces); + // this.#fearDice = `d${face}`; + } + + get dAdvantage() { + return this.dice[2]; + } + + get advantageFaces() { + return this._advantageFaces; + } + + set advantageFaces(faces) { + this._advantageFaces = this.getFaces(faces); + } + + get isCritical() { + if (!this.dHope._evaluated || !this.dFear._evaluated) return; + return this.dHope.total === this.dFear.total; + } + + get withHope() { + if (!this._evaluated) return; + return this.dHope.total > this.dFear.total; + } + + get withFear() { + if (!this._evaluated) return; + return this.dHope.total < this.dFear.total; + } + + get hasBarRally() { + return null; + } + + get totalLabel() { + const label = this.withHope + ? 'DAGGERHEART.General.Hope' + : this.withFear + ? 'DAGGERHEART.General.Fear' + : 'DAGGERHEART.General.CriticalSuccess'; + + return game.i18n.localize(label); + } + + updateFormula() {} + + createBaseDice() { + if ( + this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie && + this.dice[1] instanceof CONFIG.Dice.daggerheart.DualityDie + ) { + this.terms = [this.terms[0], this.terms[1], this.terms[2]]; + return; + } + this.terms[0] = new CONFIG.Dice.daggerheart.DualityDie(); + this.terms[1] = new foundry.dice.terms.OperatorTerm({ operator: '+' }); + this.terms[2] = new CONFIG.Dice.daggerheart.DualityDie(); + } + + applyAdvantage() { + const dieFaces = this.advantageFaces, + bardRallyFaces = this.hasBarRally, + advDie = new foundry.dice.terms.Die({ faces: dieFaces }); + if (this.hasAdvantage || this.hasDisadvantage || bardRallyFaces) + this.terms.push(new foundry.dice.terms.OperatorTerm({ operator: this.hasDisadvantage ? '-' : '+' })); + if (bardRallyFaces) { + const rallyDie = new foundry.dice.terms.Die({ faces: bardRallyFaces }); + if (this.hasAdvantage) { + this.terms.push( + new foundry.dice.terms.PoolTerm({ + terms: [advDie.formula, rallyDie.formula], + modifiers: ['kh'] + }) + ); + } else if (this.hasDisadvantage) { + this.terms.push(advDie, new foundry.dice.terms.OperatorTerm({ operator: '+' }), rallyDie); + } + } else if (this.hasAdvantage || this.hasDisadvantage) this.terms.push(advDie); + } + + applyBaseBonus() { + this.options.roll.modifiers = []; + if (!this.options.roll.trait) return; + this.options.roll.modifiers.push({ + label: `DAGGERHEART.Abilities.${this.options.roll.trait}.name`, + value: Roll.replaceFormulaData(`@traits.${this.options.roll.trait}.total`, this.data) + }); + } + + static postEvaluate(roll, config = {}) { + super.postEvaluate(roll, config); + config.roll.hope = { + dice: roll.dHope.denomination, + value: roll.dHope.total + }; + config.roll.fear = { + dice: roll.dFear.denomination, + value: roll.dFear.total + }; + config.roll.result = { + duality: roll.withHope ? 1 : roll.withFear ? -1 : 0, + total: roll.dHope.total + roll.dFear.total, + label: roll.totalLabel + }; + } +} diff --git a/module/documents/_module.mjs b/module/documents/_module.mjs index 668010c9..4dfa6264 100644 --- a/module/documents/_module.mjs +++ b/module/documents/_module.mjs @@ -3,5 +3,4 @@ export { default as DHItem } from './item.mjs'; export { default as DhpCombat } from './combat.mjs'; export { default as DhActiveEffect } from './activeEffect.mjs'; export { default as DhChatMessage } from './chatMessage.mjs'; -export * as DhRoll from '../dice/dhRolls.mjs'; export { default as DhTooltipManager } from './tooltipManager.mjs'; diff --git a/module/documents/tooltipManager.mjs b/module/documents/tooltipManager.mjs index 53668813..b780dfa9 100644 --- a/module/documents/tooltipManager.mjs +++ b/module/documents/tooltipManager.mjs @@ -1,4 +1,4 @@ -export default class DhTooltipManager extends foundry.helpers.interaction.TooltipManager.implementation { +export default class DhTooltipManager extends foundry.helpers.interaction.TooltipManager { async activate(element, options = {}) { let html = options.html; if (element.dataset.tooltip.startsWith('#item#')) { diff --git a/module/enrichers/_module.mjs b/module/enrichers/_module.mjs index 4ba1bdb6..1907f117 100644 --- a/module/enrichers/_module.mjs +++ b/module/enrichers/_module.mjs @@ -1,4 +1,2 @@ -import DhDualityRollEnricher from './DualityRollEnricher.mjs'; -import DhTemplateEnricher from './TemplateEnricher.mjs'; - -export { DhDualityRollEnricher, DhTemplateEnricher }; +export { default as DhDualityRollEnricher } from './DualityRollEnricher.mjs'; +export { default as DhTemplateEnricher } from './TemplateEnricher.mjs'; diff --git a/module/helpers/_module.mjs b/module/helpers/_module.mjs new file mode 100644 index 00000000..d7baca50 --- /dev/null +++ b/module/helpers/_module.mjs @@ -0,0 +1,2 @@ +export { default as HandlebarsHelper } from './handlebarsHelper.mjs'; +export * as utils from './utils.mjs'; diff --git a/module/systemRegistration/_module.mjs b/module/systemRegistration/_module.mjs index 555bd03f..38dcac4f 100644 --- a/module/systemRegistration/_module.mjs +++ b/module/systemRegistration/_module.mjs @@ -1,5 +1,3 @@ -import { preloadHandlebarsTemplates as handlebarsRegistration } from './handlebars.mjs'; -import * as settingsRegistration from './settings.mjs'; -import * as socketRegistration from './socket.mjs'; - -export { handlebarsRegistration, settingsRegistration, socketRegistration }; +export { preloadHandlebarsTemplates as handlebarsRegistration } from './handlebars.mjs'; +export * as settingsRegistration from './settings.mjs'; +export * as socketRegistration from './socket.mjs';