diff --git a/daggerheart.mjs b/daggerheart.mjs index 7ae01590..77e9831e 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -58,9 +58,6 @@ CONFIG.Canvas.layers.tokens.layerClass = DhTokenLayer; CONFIG.MeasuredTemplate.objectClass = placeables.DhMeasuredTemplate; -CONFIG.RollTable.documentClass = documents.DhRollTable; -CONFIG.RollTable.resultTemplate = 'systems/daggerheart/templates/ui/chat/table-result.hbs'; - CONFIG.Scene.documentClass = documents.DhScene; CONFIG.Token.documentClass = documents.DhToken; @@ -108,7 +105,7 @@ Hooks.once('init', () => { type: game.i18n.localize(typePath) }); - const { Items, Actors, RollTables } = foundry.documents.collections; + const { Items, Actors } = foundry.documents.collections; Items.unregisterSheet('core', foundry.applications.sheets.ItemSheetV2); Items.registerSheet(SYSTEM.id, applications.sheets.items.Ancestry, { types: ['ancestry'], @@ -193,12 +190,6 @@ Hooks.once('init', () => { label: sheetLabel('TYPES.Actor.party') }); - RollTables.unregisterSheet('core', foundry.applications.sheets.RollTableSheet); - RollTables.registerSheet(SYSTEM.id, applications.sheets.rollTables.RollTableSheet, { - types: ['base'], - makeDefault: true - }); - DocumentSheetConfig.unregisterSheet( CONFIG.ActiveEffect.documentClass, 'core', diff --git a/lang/en.json b/lang/en.json index 4d6815c3..fbd8f34c 100755 --- a/lang/en.json +++ b/lang/en.json @@ -488,9 +488,7 @@ "tokenHUD": { "genericEffects": "Foundry Effects", "depositPartyTokens": "Deposit Party Tokens", - "retrievePartyTokens": "Retrieve Party Tokens", - "depositCompanionTokens": "Deposit Companion Token", - "retrieveCompanionTokens": "Retrieve Companion Token" + "retrievePartyTokens": "Retrieve Party Tokens" } }, "ImageSelect": { @@ -2383,12 +2381,6 @@ "secondaryWeapon": "Secondary Weapon" } }, - "ROLLTABLES": { - "FIELDS": { - "formulaName": { "label": "Formula Name" } - }, - "formula": "Formula" - }, "SETTINGS": { "Appearance": { "FIELDS": { diff --git a/module/applications/dialogs/d20RollDialog.mjs b/module/applications/dialogs/d20RollDialog.mjs index 4a4b1556..6f320152 100644 --- a/module/applications/dialogs/d20RollDialog.mjs +++ b/module/applications/dialogs/d20RollDialog.mjs @@ -109,17 +109,11 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio context.roll = this.roll; context.rollType = this.roll?.constructor.name; context.rallyDie = this.roll.rallyChoices; - - const actorExperiences = this.config.data?.system?.experiences || {}; - const companionExperiences = this.config.roll.companionRoll - ? (this.config.data?.companion?.system.experiences ?? {}) - : null; - const experiences = companionExperiences ?? actorExperiences; + const experiences = this.config.data?.system?.experiences || {}; context.experiences = Object.keys(experiences).map(id => ({ id, ...experiences[id] })); - context.selectedExperiences = this.config.experiences; context.advantage = this.config.roll?.advantage; context.disadvantage = this.config.roll?.disadvantage; diff --git a/module/applications/hud/tokenHUD.mjs b/module/applications/hud/tokenHUD.mjs index 77caaaff..87c3e88e 100644 --- a/module/applications/hud/tokenHUD.mjs +++ b/module/applications/hud/tokenHUD.mjs @@ -5,8 +5,7 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD { classes: ['daggerheart'], actions: { combat: DHTokenHUD.#onToggleCombat, - togglePartyTokens: DHTokenHUD.#togglePartyTokens, - toggleCompanions: DHTokenHUD.#toggleCompanions + togglePartyTokens: DHTokenHUD.#togglePartyTokens } }; @@ -27,7 +26,7 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD { context.partyOnCanvas = this.actor.type === 'party' && this.actor.system.partyMembers.some(member => member.getActiveTokens().length > 0); - context.icons.toggleClowncar = 'systems/daggerheart/assets/icons/arrow-dunk.png'; + context.icons.toggleParty = 'systems/daggerheart/assets/icons/arrow-dunk.png'; context.actorType = this.actor.type; context.usesEffects = this.actor.type !== 'party'; context.canToggleCombat = DHTokenHUD.#nonCombatTypes.includes(this.actor.type) @@ -57,9 +56,6 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD { }, {}) : null; - context.hasCompanion = this.actor.system.companion; - context.companionOnCanvas = context.hasCompanion && this.actor.system.companion.getActiveTokens().length > 0; - return context; } @@ -105,24 +101,8 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD { : 'DAGGERHEART.APPLICATIONS.HUD.tokenHUD.depositPartyTokens' ); - await this.toggleClowncar(this.actor.system.partyMembers); - } - - static async #toggleCompanions(_, button) { - const icon = button.querySelector('img'); - icon.classList.toggle('flipped'); - button.dataset.tooltip = game.i18n.localize( - icon.classList.contains('flipped') - ? 'DAGGERHEART.APPLICATIONS.HUD.tokenHUD.retrieveCompanionTokens' - : 'DAGGERHEART.APPLICATIONS.HUD.tokenHUD.depositCompanionTokens' - ); - - await this.toggleClowncar([this.actor.system.companion]); - } - - async toggleClowncar(actors) { const animationDuration = 500; - const activeTokens = actors.flatMap(member => member.getActiveTokens()); + const activeTokens = this.actor.system.partyMembers.flatMap(member => member.getActiveTokens()); const { x: actorX, y: actorY } = this.document; if (activeTokens.length > 0) { for (let token of activeTokens) { @@ -134,15 +114,14 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD { } } else { const activeScene = game.scenes.find(x => x.id === game.user.viewedScene); - const tokenData = []; - for (let member of actors) { + const partyTokenData = []; + for (let member of this.actor.system.partyMembers) { const data = await member.getTokenDocument(); - tokenData.push(data.toObject()); + partyTokenData.push(data.toObject()); } - const newTokens = await activeScene.createEmbeddedDocuments( 'Token', - tokenData.map(tokenData => ({ + partyTokenData.map(tokenData => ({ ...tokenData, alpha: 0, x: actorX, diff --git a/module/applications/sheets-configs/action-base-config.mjs b/module/applications/sheets-configs/action-base-config.mjs index 42252362..7051ad2b 100644 --- a/module/applications/sheets-configs/action-base-config.mjs +++ b/module/applications/sheets-configs/action-base-config.mjs @@ -125,7 +125,6 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) async _prepareContext(_options) { const context = await super._prepareContext(_options, 'action'); context.source = this.action.toObject(true); - context.action = this.action; context.summons = []; for (const summon of context.source.summon ?? []) { diff --git a/module/applications/sheets/_module.mjs b/module/applications/sheets/_module.mjs index 390267d5..c503e054 100644 --- a/module/applications/sheets/_module.mjs +++ b/module/applications/sheets/_module.mjs @@ -1,4 +1,3 @@ export * as actors from './actors/_module.mjs'; export * as api from './api/_modules.mjs'; export * as items from './items/_module.mjs'; -export * as rollTables from './rollTables/_module.mjs'; diff --git a/module/applications/sheets/actors/companion.mjs b/module/applications/sheets/actors/companion.mjs index 21f09f02..9b85f622 100644 --- a/module/applications/sheets/actors/companion.mjs +++ b/module/applications/sheets/actors/companion.mjs @@ -71,10 +71,10 @@ export default class DhCompanionSheet extends DHBaseActorSheet { title: `${game.i18n.localize('DAGGERHEART.GENERAL.Roll.action')}: ${this.actor.name}`, headerTitle: `Companion ${game.i18n.localize('DAGGERHEART.GENERAL.Roll.action')}`, roll: { - trait: partner.system.spellcastModifierTrait?.key, - companionRoll: true + trait: partner.system.spellcastModifierTrait?.key }, - hasRoll: true + hasRoll: true, + data: partner.getRollData() }; const result = await partner.diceRoll(config); diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 3c0444eb..b590de86 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -600,7 +600,7 @@ export default function DHApplicationMixin(Base) { { relativeTo: isAction ? doc.parent : doc, rollData: doc.getRollData?.(), - secrets: isAction ? doc.parent.parent.isOwner : doc.isOwner + secrets: isAction ? doc.parent.isOwner : doc.isOwner } ); } diff --git a/module/applications/sheets/rollTables/_module.mjs b/module/applications/sheets/rollTables/_module.mjs deleted file mode 100644 index 73067b64..00000000 --- a/module/applications/sheets/rollTables/_module.mjs +++ /dev/null @@ -1 +0,0 @@ -export { default as RollTableSheet } from './rollTable.mjs'; diff --git a/module/applications/sheets/rollTables/rollTable.mjs b/module/applications/sheets/rollTables/rollTable.mjs deleted file mode 100644 index 9ead6814..00000000 --- a/module/applications/sheets/rollTables/rollTable.mjs +++ /dev/null @@ -1,191 +0,0 @@ -export default class DhRollTableSheet extends foundry.applications.sheets.RollTableSheet { - static DEFAULT_OPTIONS = { - ...super.DEFAULT_OPTIONS, - actions: { - changeMode: DhRollTableSheet.#onChangeMode, - drawResult: DhRollTableSheet.#onDrawResult, - resetResults: DhRollTableSheet.#onResetResults, - addFormula: DhRollTableSheet.#addFormula, - removeFormula: DhRollTableSheet.#removeFormula - } - }; - - static buildParts() { - const { footer, header, sheet, results, ...parts } = super.PARTS; - return { - sheet: { - ...sheet, - template: 'systems/daggerheart/templates/sheets/rollTable/sheet.hbs' - }, - header: { template: 'systems/daggerheart/templates/sheets/rollTable/header.hbs' }, - ...parts, - results: { - template: 'systems/daggerheart/templates/sheets/rollTable/results.hbs', - templates: ['templates/sheets/roll-table/result-details.hbs'], - scrollable: ['table[data-results] tbody'] - }, - summary: { template: 'systems/daggerheart/templates/sheets/rollTable/summary.hbs' }, - footer - }; - } - - static PARTS = DhRollTableSheet.buildParts(); - - async _preRender(context, options) { - await super._preRender(context, options); - - if (!options.internalRefresh) - this.daggerheartFlag = new game.system.api.data.DhRollTable(this.document.flags.daggerheart); - } - - /* root PART has a blank element on _attachPartListeners, so it cannot be used to set the eventListeners for the view mode */ - async _onRender(context, options) { - super._onRender(context, options); - - for (const element of this.element.querySelectorAll('.system-update-field')) - element.addEventListener('change', this.updateSystemField.bind(this)); - } - - async _preparePartContext(partId, context, options) { - context = await super._preparePartContext(partId, context, options); - - switch (partId) { - case 'sheet': - context.altFormula = this.daggerheartFlag.altFormula; - context.usesAltFormula = Object.keys(this.daggerheartFlag.altFormula).length > 0; - context.altFormulaOptions = { - '': { name: this.daggerheartFlag.formulaName }, - ...this.daggerheartFlag.altFormula - }; - context.activeAltFormula = this.daggerheartFlag.activeAltFormula; - context.selectedFormula = this.daggerheartFlag.getActiveFormula(this.document.formula); - context.results = this.getExtendedResults(context.results); - break; - case 'header': - context.altFormula = this.daggerheartFlag.altFormula; - context.usesAltFormula = Object.keys(this.daggerheartFlag.altFormula).length > 0; - context.altFormulaOptions = { - '': { name: this.daggerheartFlag.formulaName }, - ...this.daggerheartFlag.altFormula - }; - context.activeAltFormula = this.daggerheartFlag.activeAltFormula; - break; - case 'summary': - context.systemFields = this.daggerheartFlag.schema.fields; - context.altFormula = this.daggerheartFlag.altFormula; - context.formulaName = this.daggerheartFlag.formulaName; - break; - case 'results': - context.results = this.getExtendedResults(context.results); - break; - } - - return context; - } - - getExtendedResults(results) { - const bodyDarkMode = document.body.classList.contains('theme-dark'); - const elementLightMode = this.element.classList.contains('theme-light'); - const elementDarkMode = this.element.classList.contains('theme-dark'); - const isDarkMode = elementDarkMode || (!elementLightMode && bodyDarkMode); - - return results.map(x => ({ - ...x, - displayImg: isDarkMode && x.img === 'icons/svg/d20-black.svg' ? 'icons/svg/d20.svg' : x.img - })); - } - - /* -------------------------------------------- */ - /* Flag SystemData update methods */ - /* -------------------------------------------- */ - - async updateSystemField(event) { - const { dataset, value } = event.target; - await this.daggerheartFlag.updateSource({ [dataset.path]: value }); - this.render({ internalRefresh: true }); - } - - getSystemFlagUpdate() { - const deleteUpdate = Object.keys(this.document._source.flags.daggerheart?.altFormula ?? {}).reduce( - (acc, formulaKey) => { - if (!this.daggerheartFlag.altFormula[formulaKey]) acc.altFormula[`-=${formulaKey}`] = null; - - return acc; - }, - { altFormula: {} } - ); - - return { ['flags.daggerheart']: foundry.utils.mergeObject(this.daggerheartFlag.toObject(), deleteUpdate) }; - } - - static async #addFormula() { - await this.daggerheartFlag.updateSource({ - [`altFormula.${foundry.utils.randomID()}`]: game.system.api.data.DhRollTable.getDefaultFormula() - }); - this.render({ internalRefresh: true }); - } - - static async #removeFormula(_event, target) { - await this.daggerheartFlag.updateSource({ - [`altFormula.-=${target.dataset.key}`]: null - }); - this.render({ internalRefresh: true }); - } - - /* -------------------------------------------- */ - /* Extended RollTable methods */ - /* -------------------------------------------- */ - - /** - * Alternate between view and edit modes. - * @this {RollTableSheet} - * @type {ApplicationClickAction} - */ - static async #onChangeMode() { - this.mode = this.isEditMode ? 'view' : 'edit'; - await this.document.update(this.getSystemFlagUpdate()); - await this.render({ internalRefresh: true }); - } - - /** @inheritdoc */ - async _processSubmitData(event, form, submitData, options) { - /* RollTable sends an empty dummy event when swapping from view/edit first time */ - if (Object.keys(submitData).length) { - if (!submitData.flags) submitData.flags = { daggerheart: {} }; - submitData.flags.daggerheart = this.getSystemFlagUpdate(); - } - - super._processSubmitData(event, form, submitData, options); - } - - /** @inheritdoc */ - static async #onResetResults() { - await this.document.update(this.getSystemFlagUpdate()); - await this.document.resetResults(); - } - - /** - * Roll and draw a TableResult. - * @this {RollTableSheet} - * @type {ApplicationClickAction} - */ - static async #onDrawResult(_event, button) { - if (this.form) await this.submit({ operation: { render: false } }); - button.disabled = true; - const table = this.document; - - await this.document.update(this.getSystemFlagUpdate()); - - /* Sending in the currently selectd activeFormula to table.roll to use as the formula */ - const selectedFormula = this.daggerheartFlag.getActiveFormula(this.document.formula); - const tableRoll = await table.roll({ selectedFormula }); - const draws = table.getResultsForRoll(tableRoll.roll.total); - if (draws.length > 0) { - if (game.settings.get('core', 'animateRollTable')) await this._animateRoll(draws); - await table.draw(tableRoll); - } - - // Reenable the button if drawing with replacement since the draw won't trigger a sheet re-render - if (table.replacement) button.disabled = false; - } -} diff --git a/module/data/_module.mjs b/module/data/_module.mjs index f7e25a4e..7ad20808 100644 --- a/module/data/_module.mjs +++ b/module/data/_module.mjs @@ -1,7 +1,6 @@ export { default as DhCombat } from './combat.mjs'; export { default as DhCombatant } from './combatant.mjs'; export { default as DhTagTeamRoll } from './tagTeamRoll.mjs'; -export { default as DhRollTable } from './rollTable.mjs'; export { default as RegisteredTriggers } from './registeredTriggers.mjs'; export * as countdowns from './countdowns.mjs'; diff --git a/module/data/actor/base.mjs b/module/data/actor/base.mjs index 08308eab..b90361e2 100644 --- a/module/data/actor/base.mjs +++ b/module/data/actor/base.mjs @@ -27,7 +27,7 @@ const resistanceField = (resistanceLabel, immunityLabel, reductionLabel) => }); /* Common rules applying to Characters and Adversaries */ -export const commonActorRules = (extendedData = { damageReduction: {}, attack: { damage: {} } }) => ({ +export const commonActorRules = (extendedData = { damageReduction: {} }) => ({ conditionImmunities: new fields.SchemaField({ hidden: new fields.BooleanField({ initial: false }), restrained: new fields.BooleanField({ initial: false }), @@ -41,23 +41,7 @@ export const commonActorRules = (extendedData = { damageReduction: {}, attack: { magical: new fields.NumberField({ initial: 0, min: 0 }), physical: new fields.NumberField({ initial: 0, min: 0 }) }), - ...(extendedData.damageReduction ?? {}) - }), - attack: new fields.SchemaField({ - ...extendedData.attack, - damage: new fields.SchemaField({ - hpDamageMultiplier: new fields.NumberField({ - required: true, - nullable: false, - initial: 1 - }), - hpDamageTakenMultiplier: new fields.NumberField({ - required: true, - nullable: false, - initial: 1 - }), - ...(extendedData.attack?.damage ?? {}) - }) + ...extendedData.damageReduction }) }); diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 594f078c..12396384 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -253,35 +253,35 @@ export default class DhCharacter extends BaseDataActor { hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark.hint' }), disabledArmor: new fields.BooleanField({ intial: false }) - }, - attack: { - damage: { - diceIndex: new fields.NumberField({ - integer: true, - min: 0, - max: 5, - initial: 0, - label: 'DAGGERHEART.GENERAL.Rules.attack.damage.dice.label', - hint: 'DAGGERHEART.GENERAL.Rules.attack.damage.dice.hint' - }), - bonus: new fields.NumberField({ - required: true, - initial: 0, - min: 0, - label: 'DAGGERHEART.GENERAL.Rules.attack.damage.bonus.label' - }) - }, - roll: new fields.SchemaField({ - trait: new fields.StringField({ - required: true, - choices: CONFIG.DH.ACTOR.abilities, - nullable: true, - initial: null, - label: 'DAGGERHEART.GENERAL.Rules.attack.roll.trait.label' - }) - }) } }), + attack: new fields.SchemaField({ + damage: new fields.SchemaField({ + diceIndex: new fields.NumberField({ + integer: true, + min: 0, + max: 5, + initial: 0, + label: 'DAGGERHEART.GENERAL.Rules.attack.damage.dice.label', + hint: 'DAGGERHEART.GENERAL.Rules.attack.damage.dice.hint' + }), + bonus: new fields.NumberField({ + required: true, + initial: 0, + min: 0, + label: 'DAGGERHEART.GENERAL.Rules.attack.damage.bonus.label' + }) + }), + roll: new fields.SchemaField({ + trait: new fields.StringField({ + required: true, + choices: CONFIG.DH.ACTOR.abilities, + nullable: true, + initial: null, + label: 'DAGGERHEART.GENERAL.Rules.attack.roll.trait.label' + }) + }) + }), dualityRoll: new fields.SchemaField({ defaultHopeDice: new fields.NumberField({ nullable: false, @@ -368,7 +368,7 @@ export default class DhCharacter extends BaseDataActor { const modifiers = subClasses ?.map(sc => ({ ...this.traits[sc.system.spellcastingTrait], key: sc.system.spellcastingTrait })) .filter(x => x); - return modifiers.sort((a, b) => (b.value ?? 0) - (a.value ?? 0))[0]; + return modifiers.sort((a, b) => a.value - b.value)[0]; } get spellcastModifier() { @@ -677,8 +677,6 @@ export default class DhCharacter extends BaseDataActor { } } } - - this.companion.system.attack.roll.bonus = this.traits.instinct.value; } this.resources.hope.value = Math.min(baseHope, this.resources.hope.max); diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index ef91c64e..bb81c702 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -105,22 +105,12 @@ export default class DamageField extends fields.SchemaField { damagePromises.push( actor.takeHealing(config.damage).then(updates => targetDamage.push({ token, updates })) ); - else { - const configDamage = foundry.utils.deepClone(config.damage); - const hpDamageMultiplier = config.actionActor?.system.rules.attack.damage.hpDamageMultiplier ?? 1; - const hpDamageTakenMultiplier = actor.system.rules.attack.damage.hpDamageTakenMultiplier; - if (configDamage.hitPoints) { - for (const part of configDamage.hitPoints.parts) { - part.total = Math.ceil(part.total * hpDamageMultiplier * hpDamageTakenMultiplier); - } - } - + else damagePromises.push( actor - .takeDamage(configDamage, config.isDirect) + .takeDamage(config.damage, config.isDirect) .then(updates => targetDamage.push({ token, updates })) ); - } } Promise.all(damagePromises).then(async _ => { diff --git a/module/data/item/base.mjs b/module/data/item/base.mjs index 84f39103..2399b7db 100644 --- a/module/data/item/base.mjs +++ b/module/data/item/base.mjs @@ -147,7 +147,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { return await foundry.applications.ux.TextEditor.implementation.enrichHTML(fullDescription, { relativeTo: this, rollData: this.getRollData(), - secrets: this.parent.isOwner + secrets: this.isOwner }); } diff --git a/module/data/rollTable.mjs b/module/data/rollTable.mjs deleted file mode 100644 index 78f7e6dd..00000000 --- a/module/data/rollTable.mjs +++ /dev/null @@ -1,38 +0,0 @@ -import FormulaField from './fields/formulaField.mjs'; - -//Extra definitions for RollTable -export default class DhRollTable extends foundry.abstract.TypeDataModel { - static defineSchema() { - const fields = foundry.data.fields; - - return { - formulaName: new fields.StringField({ - required: true, - nullable: false, - initial: 'Roll Formula', - label: 'DAGGERHEART.ROLLTABLES.FIELDS.formulaName.label' - }), - altFormula: new fields.TypedObjectField( - new fields.SchemaField({ - name: new fields.StringField({ - required: true, - nullable: false, - initial: 'Roll Formula', - label: 'DAGGERHEART.ROLLTABLES.FIELDS.formulaName.label' - }), - formula: new FormulaField({ label: 'Formula Roll', initial: '1d20' }) - }) - ), - activeAltFormula: new fields.StringField({ nullable: true, initial: null }) - }; - } - - getActiveFormula(baseFormula) { - return this.activeAltFormula ? (this.altFormula[this.activeAltFormula]?.formula ?? baseFormula) : baseFormula; - } - - static getDefaultFormula = () => ({ - name: game.i18n.localize('Roll Formula'), - formula: '1d20' - }); -} diff --git a/module/dice/d20Roll.mjs b/module/dice/d20Roll.mjs index f117ff65..3ddd8027 100644 --- a/module/dice/d20Roll.mjs +++ b/module/dice/d20Roll.mjs @@ -99,14 +99,11 @@ export default class D20Roll extends DHRoll { this.options.roll.modifiers = this.applyBaseBonus(); - const actorExperiences = this.options.roll.companionRoll - ? (this.options.data?.companion?.system.experiences ?? {}) - : (this.options.data.system?.experiences ?? {}); this.options.experiences?.forEach(m => { - if (actorExperiences[m]) + if (this.options.data.system?.experiences?.[m]) this.options.roll.modifiers.push({ - label: actorExperiences[m].name, - value: actorExperiences[m].value + label: this.options.data.system.experiences[m].name, + value: this.options.data.system.experiences[m].value }); }); diff --git a/module/documents/_module.mjs b/module/documents/_module.mjs index b9cfd3f2..8073cfe1 100644 --- a/module/documents/_module.mjs +++ b/module/documents/_module.mjs @@ -4,7 +4,6 @@ export { default as DhpCombat } from './combat.mjs'; export { default as DHCombatant } from './combatant.mjs'; export { default as DhActiveEffect } from './activeEffect.mjs'; export { default as DhChatMessage } from './chatMessage.mjs'; -export { default as DhRollTable } from './rollTable.mjs'; export { default as DhScene } from './scene.mjs'; export { default as DhToken } from './token.mjs'; export { default as DhTooltipManager } from './tooltipManager.mjs'; diff --git a/module/documents/rollTable.mjs b/module/documents/rollTable.mjs deleted file mode 100644 index 50b8fe63..00000000 --- a/module/documents/rollTable.mjs +++ /dev/null @@ -1,122 +0,0 @@ -export default class DhRollTable extends foundry.documents.RollTable { - async roll({ selectedFormula, roll, recursive = true, _depth = 0 } = {}) { - // Prevent excessive recursion - if (_depth > 5) { - throw new Error(`Maximum recursion depth exceeded when attempting to draw from RollTable ${this.id}`); - } - - const formula = selectedFormula ?? this.formula; - - // If there is no formula, automatically calculate an even distribution - if (!this.formula) { - await this.normalize(); - } - - // Reference the provided roll formula - roll = roll instanceof Roll ? roll : Roll.create(formula); - let results = []; - - // Ensure that at least one non-drawn result remains - const available = this.results.filter(r => !r.drawn); - if (!available.length) { - ui.notifications.warn(game.i18n.localize('TABLE.NoAvailableResults')); - return { roll, results }; - } - - // Ensure that results are available within the minimum/maximum range - const minRoll = (await roll.reroll({ minimize: true })).total; - const maxRoll = (await roll.reroll({ maximize: true })).total; - const availableRange = available.reduce( - (range, result) => { - const r = result.range; - if (!range[0] || r[0] < range[0]) range[0] = r[0]; - if (!range[1] || r[1] > range[1]) range[1] = r[1]; - return range; - }, - [null, null] - ); - if (availableRange[0] > maxRoll || availableRange[1] < minRoll) { - ui.notifications.warn('No results can possibly be drawn from this table and formula.'); - return { roll, results }; - } - - // Continue rolling until one or more results are recovered - let iter = 0; - while (!results.length) { - if (iter >= 10000) { - ui.notifications.error( - `Failed to draw an available entry from Table ${this.name}, maximum iteration reached` - ); - break; - } - roll = await roll.reroll(); - results = this.getResultsForRoll(roll.total); - iter++; - } - - // Draw results recursively from any inner Roll Tables - if (recursive) { - const inner = []; - for (const result of results) { - const { type, documentUuid } = result; - const documentName = foundry.utils.parseUuid(documentUuid)?.type; - if (type === 'document' && documentName === 'RollTable') { - const innerTable = await fromUuid(documentUuid); - if (innerTable) { - const innerRoll = await innerTable.roll({ _depth: _depth + 1 }); - inner.push(...innerRoll.results); - } - } else inner.push(result); - } - results = inner; - } - - // Return the Roll and the results - return { roll, results }; - } - - async toMessage(results, { roll, messageData = {}, messageOptions = {} } = {}) { - messageOptions.rollMode ??= game.settings.get('core', 'rollMode'); - - // Construct chat data - messageData = foundry.utils.mergeObject( - { - author: game.user.id, - speaker: foundry.documents.ChatMessage.implementation.getSpeaker(), - rolls: [], - sound: roll ? CONFIG.sounds.dice : null, - flags: { 'core.RollTable': this.id } - }, - messageData - ); - if (roll) messageData.rolls.push(roll); - - // Render the chat card which combines the dice roll with the drawn results - const detailsPromises = await Promise.allSettled(results.map(r => r.getHTML())); - const flavorKey = `TABLE.DrawFlavor${results.length > 1 ? 'Plural' : ''}`; - const flavor = game.i18n.format(flavorKey, { - number: results.length, - name: foundry.utils.escapeHTML(this.name) - }); - messageData.content = await foundry.applications.handlebars.renderTemplate(CONFIG.RollTable.resultTemplate, { - description: await TextEditor.implementation.enrichHTML(this.description, { - documents: true, - secrets: this.isOwner - }), - flavor: flavor, - results: results.map((result, i) => { - const r = result.toObject(false); - r.details = detailsPromises[i].value ?? ''; - const useTableIcon = - result.icon === CONFIG.RollTable.resultIcon && this.img !== this.constructor.DEFAULT_ICON; - r.icon = useTableIcon ? this.img : result.icon; - return r; - }), - rollHTML: this.displayRoll && roll ? await roll.render() : null, - table: this - }); - - // Create the chat message - return foundry.documents.ChatMessage.implementation.create(messageData, messageOptions); - } -} diff --git a/module/enrichers/DualityRollEnricher.mjs b/module/enrichers/DualityRollEnricher.mjs index f6de8107..91149fd8 100644 --- a/module/enrichers/DualityRollEnricher.mjs +++ b/module/enrichers/DualityRollEnricher.mjs @@ -107,7 +107,6 @@ export const enrichedDualityRoll = async ( if (target) { const result = await target.diceRoll(config); - if (!result) return; result.resourceUpdates.updateResources(); } else { // For no target, call DualityRoll directly with basic data diff --git a/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json b/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json index 830848c3..188b2687 100644 --- a/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json +++ b/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json @@ -235,51 +235,7 @@ }, "_id": "2ESeh4tPhr6DI5ty", "img": "icons/magic/death/skull-horned-worn-fire-blue.webp", - "effects": [ - { - "name": "Depths Of Despair", - "type": "base", - "system": { - "rangeDependence": { - "enabled": false, - "type": "withinRange", - "target": "hostile", - "range": "melee" - } - }, - "_id": "nofxm1vGZ2TmceA2", - "img": "icons/magic/death/skull-horned-worn-fire-blue.webp", - "changes": [ - { - "key": "system.rules.attack.damage.hpDamageMultiplier", - "mode": 5, - "value": "2", - "priority": null - } - ], - "disabled": true, - "duration": { - "startTime": null, - "combat": null, - "seconds": null, - "rounds": null, - "turns": null, - "startRound": null, - "startTurn": null - }, - "description": "

The Demon of Despair deals double damage to PCs with 0 Hope.

", - "origin": null, - "tint": "#ffffff", - "transfer": true, - "statuses": [], - "sort": 0, - "flags": {}, - "_stats": { - "compendiumSource": null - }, - "_key": "!actors.items.effects!kE4dfhqmIQpNd44e.2ESeh4tPhr6DI5ty.nofxm1vGZ2TmceA2" - } - ], + "effects": [], "folder": null, "sort": 0, "ownership": { diff --git a/src/packs/adversaries/adversary_Failed_Experiment_ChwwVqowFw8hJQwT.json b/src/packs/adversaries/adversary_Failed_Experiment_ChwwVqowFw8hJQwT.json index 408d5102..39800002 100644 --- a/src/packs/adversaries/adversary_Failed_Experiment_ChwwVqowFw8hJQwT.json +++ b/src/packs/adversaries/adversary_Failed_Experiment_ChwwVqowFw8hJQwT.json @@ -304,51 +304,7 @@ }, "_id": "1fE6xo8yIOmZkGNE", "img": "icons/skills/melee/strike-slashes-orange.webp", - "effects": [ - { - "name": "Overwhelm", - "type": "base", - "system": { - "rangeDependence": { - "enabled": false, - "type": "withinRange", - "target": "hostile", - "range": "melee" - } - }, - "_id": "eGB9G0ljYCcdGbOx", - "img": "icons/skills/melee/strike-slashes-orange.webp", - "changes": [ - { - "key": "system.rules.attack.damage.hpDamageMultiplier", - "mode": 5, - "value": "2", - "priority": null - } - ], - "disabled": true, - "duration": { - "startTime": null, - "combat": null, - "seconds": null, - "rounds": null, - "turns": null, - "startRound": null, - "startTurn": null - }, - "description": "

When a target the Failed Experiment attacks has other adversaries within Very Close range, the Failed Experiment deals double damage.

", - "origin": null, - "tint": "#ffffff", - "transfer": true, - "statuses": [], - "sort": 0, - "flags": {}, - "_stats": { - "compendiumSource": null - }, - "_key": "!actors.items.effects!ChwwVqowFw8hJQwT.1fE6xo8yIOmZkGNE.eGB9G0ljYCcdGbOx" - } - ], + "effects": [], "folder": null, "sort": 0, "ownership": { diff --git a/src/packs/adversaries/adversary_Hallowed_Archer_kabueAo6BALApWqp.json b/src/packs/adversaries/adversary_Hallowed_Archer_kabueAo6BALApWqp.json index 8cce1b94..0abf1661 100644 --- a/src/packs/adversaries/adversary_Hallowed_Archer_kabueAo6BALApWqp.json +++ b/src/packs/adversaries/adversary_Hallowed_Archer_kabueAo6BALApWqp.json @@ -229,51 +229,7 @@ }, "_id": "FGJTAeL38zTVd4fA", "img": "icons/magic/control/buff-flight-wings-runes-red-yellow.webp", - "effects": [ - { - "name": "Punish the Guilty", - "type": "base", - "system": { - "rangeDependence": { - "enabled": false, - "type": "withinRange", - "target": "hostile", - "range": "melee" - } - }, - "_id": "ID85zoIa5GfhNMti", - "img": "icons/magic/control/buff-flight-wings-runes-red-yellow.webp", - "changes": [ - { - "key": "system.rules.attack.damage.hpDamageMultiplier", - "mode": 5, - "value": "2", - "priority": null - } - ], - "disabled": true, - "duration": { - "startTime": null, - "combat": null, - "seconds": null, - "rounds": null, - "turns": null, - "startRound": null, - "startTurn": null - }, - "description": "

The Hallowed Archer deals double damage to targets marked Guilty by a High Seraph.

", - "origin": null, - "tint": "#ffffff", - "transfer": true, - "statuses": [], - "sort": 0, - "flags": {}, - "_stats": { - "compendiumSource": null - }, - "_key": "!actors.items.effects!kabueAo6BALApWqp.FGJTAeL38zTVd4fA.ID85zoIa5GfhNMti" - } - ], + "effects": [], "folder": null, "sort": 0, "ownership": { diff --git a/src/packs/adversaries/adversary_Jagged_Knife_Kneebreaker_CBKixLH3yhivZZuL.json b/src/packs/adversaries/adversary_Jagged_Knife_Kneebreaker_CBKixLH3yhivZZuL.json index c38260e9..fc644604 100644 --- a/src/packs/adversaries/adversary_Jagged_Knife_Kneebreaker_CBKixLH3yhivZZuL.json +++ b/src/packs/adversaries/adversary_Jagged_Knife_Kneebreaker_CBKixLH3yhivZZuL.json @@ -336,14 +336,7 @@ "range": "melee" } }, - "changes": [ - { - "key": "system.rules.attack.damage.hpDamageTakenMultiplier", - "mode": 5, - "value": "2", - "priority": null - } - ], + "changes": [], "disabled": false, "duration": { "startTime": null, @@ -357,8 +350,8 @@ "description": "", "tint": "#ffffff", "statuses": [ - "vulnerable", - "restrained" + "restrained", + "vulnerable" ], "sort": 0, "flags": {}, diff --git a/src/packs/adversaries/adversary_Skeleton_Archer_7X5q7a6ueeHs5oA9.json b/src/packs/adversaries/adversary_Skeleton_Archer_7X5q7a6ueeHs5oA9.json index 9d837ac0..e5381f6f 100644 --- a/src/packs/adversaries/adversary_Skeleton_Archer_7X5q7a6ueeHs5oA9.json +++ b/src/packs/adversaries/adversary_Skeleton_Archer_7X5q7a6ueeHs5oA9.json @@ -230,51 +230,7 @@ "subType": null, "originId": null }, - "effects": [ - { - "name": "Opportunist", - "type": "base", - "system": { - "rangeDependence": { - "enabled": false, - "type": "withinRange", - "target": "hostile", - "range": "melee" - } - }, - "_id": "O03vYbyNLO3YPZGo", - "img": "icons/skills/targeting/crosshair-triple-strike-orange.webp", - "changes": [ - { - "key": "system.rules.attack.damage.hpDamageMultiplier", - "mode": 5, - "value": "2", - "priority": null - } - ], - "disabled": true, - "duration": { - "startTime": null, - "combat": null, - "seconds": null, - "rounds": null, - "turns": null, - "startRound": null, - "startTurn": null - }, - "description": "

When two or more adversaries are within Very Close range of a creature, all damage the Skeleton Archer deals to that creature is doubled.

", - "origin": null, - "tint": "#ffffff", - "transfer": true, - "statuses": [], - "sort": 0, - "flags": {}, - "_stats": { - "compendiumSource": null - }, - "_key": "!actors.items.effects!7X5q7a6ueeHs5oA9.6mL2FQ9pQdfoDNzG.O03vYbyNLO3YPZGo" - } - ], + "effects": [], "folder": null, "sort": 0, "ownership": { diff --git a/src/packs/rolltables/tables_Consumables_tF04P02yVN1YDVel.json b/src/packs/rolltables/tables_Consumables_tF04P02yVN1YDVel.json index c3f5ffdc..c2413ec3 100644 --- a/src/packs/rolltables/tables_Consumables_tF04P02yVN1YDVel.json +++ b/src/packs/rolltables/tables_Consumables_tF04P02yVN1YDVel.json @@ -1,7 +1,7 @@ { "name": "Consumables", "img": "icons/consumables/potions/bottle-corked-red.webp", - "description": "", + "description": "

To generate a random consumable, choose a rarity, roll the designated dice, and match the total to the item in the table:

", "results": [ { "type": "document", @@ -1511,27 +1511,8 @@ "default": 0, "Bgvu4A6AMkRFOTGR": 3 }, - "flags": { - "daggerheart": { - "activeAltFormula": "", - "formulaName": "Common", - "altFormula": { - "uoUn5fRTUkyg6U2G": { - "name": "Uncommon", - "formula": "3d12" - }, - "FGxM2yoxUUUd9Eov": { - "name": "Rare", - "formula": "4d12" - }, - "HZ2hRBxu0k8IW0jC": { - "name": "Legendary", - "formula": "5d12" - } - } - } - }, - "formula": "2d12", + "flags": {}, + "formula": "1d60", "_id": "tF04P02yVN1YDVel", "sort": 300000, "_key": "!tables!tF04P02yVN1YDVel" diff --git a/src/packs/rolltables/tables_Loot_S61Shlt2I5CbLRjz.json b/src/packs/rolltables/tables_Loot_S61Shlt2I5CbLRjz.json index 2151ae81..9517eadd 100644 --- a/src/packs/rolltables/tables_Loot_S61Shlt2I5CbLRjz.json +++ b/src/packs/rolltables/tables_Loot_S61Shlt2I5CbLRjz.json @@ -1,7 +1,7 @@ { "name": "Loot", "img": "icons/commodities/treasure/brooch-gold-ruby.webp", - "description": "", + "description": "

To generate a random item, choose a rarity, roll the designated dice, and match the total to the item in the table:

", "results": [ { "type": "document", @@ -1511,27 +1511,8 @@ "default": 0, "Bgvu4A6AMkRFOTGR": 3 }, - "flags": { - "daggerheart": { - "activeAltFormula": "", - "formulaName": "Common", - "altFormula": { - "hJJtajaMk14bYM4X": { - "name": "Uncommon", - "formula": "3d12" - }, - "yDVeXdKpG7LzjHWa": { - "name": "Rare", - "formula": "4d12" - }, - "qPHNIuUgWAHauI6V": { - "name": "Legendary", - "formula": "5d12" - } - } - } - }, - "formula": "2d12", + "flags": {}, + "formula": "1d60", "_id": "S61Shlt2I5CbLRjz", "sort": 200000, "_key": "!tables!S61Shlt2I5CbLRjz" diff --git a/src/packs/rolltables/tables_Random_Objectives_I5L1dlgxXTNrCCkL.json b/src/packs/rolltables/tables_Table_of_Random_Objectives_I5L1dlgxXTNrCCkL.json similarity index 95% rename from src/packs/rolltables/tables_Random_Objectives_I5L1dlgxXTNrCCkL.json rename to src/packs/rolltables/tables_Table_of_Random_Objectives_I5L1dlgxXTNrCCkL.json index 9165f9d7..b10127e7 100644 --- a/src/packs/rolltables/tables_Random_Objectives_I5L1dlgxXTNrCCkL.json +++ b/src/packs/rolltables/tables_Table_of_Random_Objectives_I5L1dlgxXTNrCCkL.json @@ -1,7 +1,7 @@ { - "name": "Random Objectives", + "name": "Table of Random Objectives", "img": "icons/sundries/documents/document-torn-diagram-tan.webp", - "description": "", + "description": "

Layering Goals Other than Attrition into Combat

", "results": [ { "type": "text", @@ -311,20 +311,7 @@ "default": 0, "Bgvu4A6AMkRFOTGR": 3 }, - "flags": { - "daggerheart": { - "formulaName": "Roll Formula", - "altFormula": {}, - "activeAltFormula": null, - "flags": { - "daggerheart": { - "formulaName": "Roll Formula", - "altFormula": {}, - "activeAltFormula": null - } - } - } - }, + "flags": {}, "formula": "1d12", "_id": "I5L1dlgxXTNrCCkL", "sort": 400000, diff --git a/styles/less/global/chat.less b/styles/less/global/chat.less index b9478ea4..dc671e44 100644 --- a/styles/less/global/chat.less +++ b/styles/less/global/chat.less @@ -15,14 +15,6 @@ .message-header .message-header-main .message-sub-header-container h4 { color: @dark-blue; } - - .message-content { - .table-draw { - .table-description { - color: @dark; - } - } - } } } @@ -91,7 +83,6 @@ .message-content { padding-bottom: 8px; - .flavor-text { font-size: var(--font-size-12); line-height: 20px; @@ -99,33 +90,6 @@ text-align: center; display: block; } - - .table-draw { - .table-flavor { - padding-top: 5px; - padding-bottom: 0.5rem; - font-size: var(--font-size-12); - } - - .table-description { - color: @beige; - font-style: italic; - - &.flavor-spaced { - padding-top: 0; - } - } - - .table-results { - .description { - flex-basis: min-content; - - > p:first-of-type { - margin-top: 0; - } - } - } - } } } } diff --git a/styles/less/hud/token-hud/token-hud.less b/styles/less/hud/token-hud/token-hud.less index ea58f673..46003975 100644 --- a/styles/less/hud/token-hud/token-hud.less +++ b/styles/less/hud/token-hud/token-hud.less @@ -24,13 +24,13 @@ font-weight: bold; } } - } - .clown-car img { - transition: 0.5s; + .clown-car img { + transition: 0.5s; - &.flipped { - transform: scaleX(-1); + &.flipped { + transform: scaleX(-1); + } } } diff --git a/styles/less/sheets/index.less b/styles/less/sheets/index.less index 1bdb451a..216cda33 100644 --- a/styles/less/sheets/index.less +++ b/styles/less/sheets/index.less @@ -40,5 +40,4 @@ @import './items/heritage.less'; @import './items/item-sheet-shared.less'; -@import './rollTables/sheet.less'; @import './actions/actions.less'; diff --git a/styles/less/sheets/rollTables/sheet.less b/styles/less/sheets/rollTables/sheet.less deleted file mode 100644 index a7c05455..00000000 --- a/styles/less/sheets/rollTables/sheet.less +++ /dev/null @@ -1,29 +0,0 @@ -.application.sheet.roll-table-sheet { - .formulas-section { - legend { - margin-left: auto; - margin-right: auto; - } - - .formulas-container { - display: grid; - grid-template-columns: 1fr 1fr 40px; - gap: 10px; - text-align: center; - - .formula-button { - width: 100%; - display: flex; - align-items: center; - justify-content: center; - } - } - } - - .roll-table-view-formula-container { - width: fit-content; - display: flex; - align-items: center; - gap: 4px; - } -} diff --git a/templates/hud/tokenHUD.hbs b/templates/hud/tokenHUD.hbs index 1ba29621..f079e5d9 100644 --- a/templates/hud/tokenHUD.hbs +++ b/templates/hud/tokenHUD.hbs @@ -11,11 +11,6 @@ - {{#if hasCompanion}} - - {{/if}} {{#if canConfigure}} {{/if}} diff --git a/templates/sheets-settings/action-settings/base.hbs b/templates/sheets-settings/action-settings/base.hbs index 95c3cc50..65010903 100644 --- a/templates/sheets-settings/action-settings/base.hbs +++ b/templates/sheets-settings/action-settings/base.hbs @@ -11,6 +11,6 @@
{{localize "DAGGERHEART.GENERAL.description"}} - {{formInput fields.description value=source.description enriched=action.description name="description" toggled=true }} + {{formInput fields.description value=source.description enriched=source.description name="description" toggled=true }}
\ No newline at end of file diff --git a/templates/sheets/actors/character/sidebar.hbs b/templates/sheets/actors/character/sidebar.hbs index 24e68e02..0db2bf42 100644 --- a/templates/sheets/actors/character/sidebar.hbs +++ b/templates/sheets/actors/character/sidebar.hbs @@ -1,12 +1,12 @@