diff --git a/lang/en.json b/lang/en.json index 2efd6d7be..dbeb0c912 100755 --- a/lang/en.json +++ b/lang/en.json @@ -245,10 +245,6 @@ "unequip": "Unequip", "useItem": "Use Item" }, - "defaultHopeDice": "Default Hope Dice", - "defaultFearDice": "Default Fear Dice", - "defaultAdvantageDice": "Default Advantage Dice", - "defaultDisadvantageDice": "Default Disadvantage Dice", "disadvantageSources": { "label": "Disadvantage Sources", "hint": "Add single words or short text as reminders and hints of what a character has disadvantage on." @@ -314,6 +310,16 @@ }, "noPartner": "No Partner selected" }, + "Creature": { + "rules": { + "roll": { + "hope": { "label": "Default Hope Dice Index", "hint": "Index for the default hope dice. 0=d4, 1=d6, 2=d8, 3=d10, 4=d12, 5=d20" }, + "fear": { "label": "Default Fear Dice Index", "hint": "Index for the default fear dice. 0=d4, 1=d6, 2=d8, 3=d10, 4=d12, 5=d20" }, + "advantage": { "label": "Default Advantage Dice Index", "hint": "Index for the default advantage dice. 0=d4, 1=d6, 2=d8, 3=d10, 4=d12, 5=d20" }, + "disadvantage": { "label": "Default Disadvantage Dice Index", "hint": "Index for the default disadvantage dice. 0=d4, 1=d6, 2=d8, 3=d10, 4=d12, 5=d20" } + } + } + }, "Environment": { "FIELDS": { "description": { @@ -690,6 +696,9 @@ "title": "{actor} Level Up", "viewModeTitle": "{actor} Level Up (View Mode)" }, + "LevelupOptionsDialog": { + "title": "Levelup Options: {name}" + }, "MulticlassChoice": { "title": "Multiclassing - {actor}", "explanation": "You are adding {class} as your multiclass", @@ -1271,6 +1280,10 @@ "diceValue": "Dice Value", "die": "Die" }, + "LevelupData": { + "checkboxSelections": "Checkboxes", + "minCost": "Minimum Boxes Picked" + }, "Range": { "self": { "name": "Self", @@ -2483,6 +2496,7 @@ "step": "Step", "stress": "Stress", "subclasses": "Subclasses", + "subType": "Subtype", "success": "Success", "summon": { "single": "Summon", @@ -3267,6 +3281,7 @@ "rightClickExtend": "Right-Click to extend", "companionPartnerLevelBlock": "The companion needs an assigned partner to level up.", "configureAttribution": "Configure Attribution", + "configureLevelupOptions": "Configure Levelup Options", "deleteItem": "Delete Item", "immune": "Immune", "middleClick": "[Middle Click] Keep tooltip view", diff --git a/module/applications/dialogs/_module.mjs b/module/applications/dialogs/_module.mjs index c866f1cd3..bc516b9e0 100644 --- a/module/applications/dialogs/_module.mjs +++ b/module/applications/dialogs/_module.mjs @@ -17,3 +17,4 @@ export { default as TagTeamDialog } from './tagTeamDialog.mjs'; export { default as GroupRollDialog } from './groupRollDialog.mjs'; export { default as RiskItAllDialog } from './riskItAllDialog.mjs'; export { default as CompendiumBrowserSettingsDialog } from './CompendiumBrowserSettings.mjs'; +export { default as LevelupOptionsDialog } from './levelupOptionsDialog.mjs'; diff --git a/module/applications/dialogs/d20RollDialog.mjs b/module/applications/dialogs/d20RollDialog.mjs index 067aa4734..926b3a80f 100644 --- a/module/applications/dialogs/d20RollDialog.mjs +++ b/module/applications/dialogs/d20RollDialog.mjs @@ -176,11 +176,11 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio this.config.roll.advantage = this.config.roll.advantage === advantage ? 0 : advantage; - if (this.config.roll.advantage === 1 && this.config.data.rules.roll.defaultAdvantageDice) { - const faces = Number.parseInt(this.config.data.rules.roll.defaultAdvantageDice); + if (this.config.roll.advantage === 1 && this.config.data.rules.roll.advantageFaces) { + const faces = Number.parseInt(this.config.data.rules.roll.advantageFaces); this.roll.advantageFaces = Number.isNaN(faces) ? this.roll.advantageFaces : faces; - } else if (this.config.roll.advantage === -1 && this.config.data.rules.roll.defaultDisadvantageDice) { - const faces = Number.parseInt(this.config.data.rules.roll.defaultDisadvantageDice); + } else if (this.config.roll.advantage === -1 && this.config.data.rules.roll.disadvantageFaces) { + const faces = Number.parseInt(this.config.data.rules.roll.disadvantageFaces); this.roll.advantageFaces = Number.isNaN(faces) ? this.roll.advantageFaces : faces; } diff --git a/module/applications/dialogs/levelupOptionsDialog.mjs b/module/applications/dialogs/levelupOptionsDialog.mjs new file mode 100644 index 000000000..ad5f933f9 --- /dev/null +++ b/module/applications/dialogs/levelupOptionsDialog.mjs @@ -0,0 +1,110 @@ +import { LevelOptionType } from '../../data/levelTier.mjs'; + +const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; + +export default class LevelupOptionsDialog extends HandlebarsApplicationMixin(ApplicationV2) { + constructor(item) { + super({}); + + this.item = item; + this.selectedOption = null; + } + + get title() { + return game.i18n.format('DAGGERHEART.APPLICATIONS.LevelupOptionsDialog.title', { name: this.item.name }); + } + + static DEFAULT_OPTIONS = { + tag: 'form', + classes: ['daggerheart', 'dh-style', 'dialog', 'views', 'levelup-options-dialog'], + position: { width: 480, height: 'auto' }, + window: { icon: 'fa-solid fa-angles-up fa-fw' }, + actions: { + addTierOption: LevelupOptionsDialog.#addTierOption, + removeTierOption: LevelupOptionsDialog.#removeTierOption + }, + form: { handler: this.updateData, submitOnChange: true, closeOnSubmit: false } + }; + + static PARTS = { + header: { template: 'systems/daggerheart/templates/dialogs/levelupOptionsDialog/header.hbs' }, + tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, + tiers: { template: 'systems/daggerheart/templates/dialogs/levelupOptionsDialog/tiers.hbs' } + }; + + /** @inheritdoc */ + static TABS = { + primary: { + tabs: [ + { id: 'tier2', label: 'DAGGERHEART.GENERAL.Tiers.2', tier: 2 }, + { id: 'tier3', label: 'DAGGERHEART.GENERAL.Tiers.3', tier: 3 }, + { id: 'tier4', label: 'DAGGERHEART.GENERAL.Tiers.4', tier: 4 } + ], + initial: 'tier2' + } + }; + + _attachPartListeners(partId, htmlElement, options) { + super._attachPartListeners(partId, htmlElement, options); + + for (const element of htmlElement.querySelectorAll('.option-type-select')) + element.addEventListener('change', this.updateSelectedOption.bind(this)); + } + + async _prepareContext(_options) { + const context = await super._prepareContext(_options); + context.fields = this.item.system.schema.fields.levelupOptionTiers.element.element.fields; + context.item = this.item; + context.levelupOptionTiers = Object.keys(this.item.system.levelupOptionTiers).reduce((acc, key) => { + const tier = this.item.system.levelupOptionTiers[key]; + acc[key] = Object.keys(tier).reduce((acc, key) => { + const option = tier[key]; + acc[key] = { + ...option, + typeData: option.type ? LevelOptionType[option.type] : null + }; + + return acc; + }, {}); + + return acc; + }, {}); + + context.optionTypes = LevelOptionType; + context.selectedOption = this.selectedOption; + + return context; + } + + static async updateData(_event, _element, formData) { + const data = foundry.utils.expandObject(formData.object); + await this.item.update(data); + + this.render(); + } + + updateSelectedOption(event) { + this.selectedOption = event.target.value; + this.render(); + } + + static async #addTierOption(_event, button) { + const { tier } = button.dataset; + await this.item.update({ + [`system.levelupOptionTiers.${tier}.${foundry.utils.randomID()}`]: { + label: LevelOptionType[this.selectedOption].label, + type: this.selectedOption + } + }); + + this.selectedOption = null; + this.render(); + } + + static async #removeTierOption(_event, button) { + const { tier, key } = button.dataset; + + await this.item.update({ [`system.levelupOptionTiers.${tier}.${key}`]: _del }); + this.render(); + } +} diff --git a/module/applications/levelup/characterLevelup.mjs b/module/applications/levelup/characterLevelup.mjs index f7ef2ffa8..b2a090592 100644 --- a/module/applications/levelup/characterLevelup.mjs +++ b/module/applications/levelup/characterLevelup.mjs @@ -6,9 +6,7 @@ export default class DhCharacterLevelUp extends LevelUpBase { constructor(actor) { super(actor); - this.levelTiers = this.addBonusChoices( - game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers) - ); + this.levelTiers = this.addBonusChoices(actor.system.levelupTiers); const playerLevelupData = actor.system.levelData; this.levelup = new DhLevelup(DhLevelup.initializeData(this.levelTiers, playerLevelupData)); } diff --git a/module/applications/levelup/levelup.mjs b/module/applications/levelup/levelup.mjs index c4616d9a1..4a9afcac0 100644 --- a/module/applications/levelup/levelup.mjs +++ b/module/applications/levelup/levelup.mjs @@ -527,7 +527,8 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2) minCost: Number(button.dataset.cost), amount: button.dataset.amount ? Number(button.dataset.amount) : null, value: button.dataset.value, - type: button.dataset.type + type: button.dataset.type, + subType: button.dataset.subType }; if (button.dataset.type === 'domainCard') { diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 5faa5d5c0..09008aaac 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -99,7 +99,8 @@ export default function DHApplicationMixin(Base) { toggleExtended: DHSheetV2.#toggleExtended, addNewItem: DHSheetV2.#addNewItem, browseItem: DHSheetV2.#browseItem, - editAttribution: DHSheetV2.#editAttribution + editAttribution: DHSheetV2.#editAttribution, + configureLevelUpOptions: DHSheetV2.#configureLevelUpOptions }, contextMenus: [ { @@ -119,6 +120,16 @@ export default function DHApplicationMixin(Base) { } } ], + window: { + controls: [ + { + icon: 'fa-solid fa-angles-up fa-fw', + label: 'DAGGERHEART.UI.Tooltip.configureLevelupOptions', + action: 'configureLevelUpOptions', + visible: DHSheetV2.#hasLevelUpOptions + } + ] + }, dragDrop: [{ dragSelector: '.inventory-item[data-type="effect"]', dropSelector: null }], tagifyConfigs: [] }; @@ -142,6 +153,10 @@ export default function DHApplicationMixin(Base) { return frame; } + static #hasLevelUpOptions() { + return this.document.system.metadata.hasLevelUpOptions; + } + /** * Refresh the custom parts of the application frame */ @@ -709,6 +724,10 @@ export default function DHApplicationMixin(Base) { new game.system.api.applications.dialogs.AttributionDialog(this.document).render({ force: true }); } + static async #configureLevelUpOptions() { + new game.system.api.applications.dialogs.LevelupOptionsDialog(this.document).render({ force: true }); + } + /** * Create an embedded document. * @type {ApplicationClickAction} diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 1bb3560f4..5904483fe 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -261,24 +261,6 @@ export default class DhCharacter extends DhCreature { }) } }), - dualityRoll: new fields.SchemaField({ - defaultHopeDice: new fields.NumberField({ - nullable: false, - required: true, - integer: true, - choices: CONFIG.DH.GENERAL.dieFaces, - initial: 12, - label: 'DAGGERHEART.ACTORS.Character.defaultHopeDice' - }), - defaultFearDice: new fields.NumberField({ - nullable: false, - required: true, - integer: true, - choices: CONFIG.DH.GENERAL.dieFaces, - initial: 12, - label: 'DAGGERHEART.ACTORS.Character.defaultFearDice' - }) - }), burden: new fields.SchemaField({ ignore: new fields.BooleanField({ label: 'DAGGERHEART.ACTORS.Character.burden.ignore.label' }) }), @@ -287,21 +269,47 @@ export default class DhCharacter extends DhCreature { label: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.label', hint: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.hint' }), - defaultAdvantageDice: new fields.NumberField({ - nullable: true, + hopeIndex: new fields.NumberField({ + required: true, + integer: true, + min: 0, + max: 5, + initial: 4, + label: 'DAGGERHEART.ACTORS.Creature.rules.roll.hope.label', + hint: 'DAGGERHEART.ACTORS.Creature.rules.roll.hope.hint' + }), + fearIndex: new fields.NumberField({ required: true, integer: true, - choices: CONFIG.DH.GENERAL.dieFaces, - initial: null, - label: 'DAGGERHEART.ACTORS.Character.defaultAdvantageDice' + min: 0, + max: 5, + initial: 4, + label: 'DAGGERHEART.ACTORS.Creature.rules.roll.fear.label', + hint: 'DAGGERHEART.ACTORS.Creature.rules.roll.fear.hint' }), - defaultDisadvantageDice: new fields.NumberField({ - nullable: true, + advantageIndex: new fields.NumberField({ required: true, integer: true, - choices: CONFIG.DH.GENERAL.dieFaces, - initial: null, - label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice' + min: 0, + max: 5, + initial: 1, + label: 'DAGGERHEART.ACTORS.Creature.rules.roll.advantage.label', + hint: 'DAGGERHEART.ACTORS.Creature.rules.roll.advantage.hint' + }), + disadvantageIndex: new fields.NumberField({ + required: true, + integer: true, + min: 0, + max: 5, + initial: 1, + label: 'DAGGERHEART.ACTORS.Creature.rules.roll.disadvantage.label', + hint: 'DAGGERHEART.ACTORS.Creature.rules.roll.disadvantage.hint' + }), + comboDieIndex: new fields.NumberField({ + integer: true, + min: 0, + max: 5, + initial: 0 }) }) }) @@ -447,6 +455,19 @@ export default class DhCharacter extends DhCreature { return attack; } + get levelupTiers() { + const tierData = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers); + for (const tierKey of Object.keys(this.class?.value?.system.levelupOptionTiers ?? {})) { + const tier = this.class.value.system.levelupOptionTiers[tierKey]; + for (const optionKey of Object.keys(tier)) { + const option = tier[optionKey]; + tierData.tiers[tierKey].options[optionKey] = option; + } + } + + return tierData; + } + /* All items are valid on characters */ isItemValid() { return true; @@ -745,6 +766,9 @@ export default class DhCharacter extends DhCreature { } }); break; + case 'dice': + this.rules.roll[selection.subType] += 1; + break; } } } @@ -802,6 +826,14 @@ export default class DhCharacter extends DhCreature { isReversed: true }; + /* Add convience Faces properties for all dice */ + const { hopeIndex, fearIndex, advantageIndex, disadvantageIndex, comboDieIndex } = this.rules.roll; + const dice = { hopeIndex, fearIndex, advantageIndex, disadvantageIndex, comboDieIndex }; + for (const dieKey of Object.keys(dice)) { + const diceBaseKey = dieKey.replace('Index', ''); + this.rules.roll[`${diceBaseKey}Faces`] = CONFIG.DH.GENERAL.dieFaces[dice[dieKey]]; + } + this.attack.damage.parts.hitPoints.value.custom.formula = `@prof${this.basicAttackDamageDice}${this.rules.attack.damage.bonus ? ` + ${this.rules.attack.damage.bonus}` : ''}`; } diff --git a/module/data/actor/companion.mjs b/module/data/actor/companion.mjs index 538031fb2..956696c27 100644 --- a/module/data/actor/companion.mjs +++ b/module/data/actor/companion.mjs @@ -63,21 +63,23 @@ export default class DhCompanion extends DhCreature { }) }), roll: new fields.SchemaField({ - defaultAdvantageDice: new fields.NumberField({ - nullable: true, + advantage: new fields.NumberField({ required: true, integer: true, - choices: CONFIG.DH.GENERAL.dieFaces, - initial: null, - label: 'DAGGERHEART.ACTORS.Character.defaultAdvantageDice' + min: 0, + max: 5, + initial: 1, + label: 'DAGGERHEART.ACTORS.Creature.rules.roll.advantage.label', + hint: 'DAGGERHEART.ACTORS.Creature.rules.roll.advantage.hint' }), - defaultDisadvantageDice: new fields.NumberField({ - nullable: true, + disadvantage: new fields.NumberField({ required: true, integer: true, - choices: CONFIG.DH.GENERAL.dieFaces, - initial: null, - label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice' + min: 0, + max: 5, + initial: 1, + label: 'DAGGERHEART.ACTORS.Creature.rules.roll.disadvantage.label', + hint: 'DAGGERHEART.ACTORS.Creature.rules.roll.disadvantage.hint' }) }) }), diff --git a/module/data/item/class.mjs b/module/data/item/class.mjs index d37383180..f1f7a96de 100644 --- a/module/data/item/class.mjs +++ b/module/data/item/class.mjs @@ -3,6 +3,7 @@ import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs'; import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs'; import ItemLinkFields from '../fields/itemLinkFields.mjs'; import { addLinkedItemsDiff, getFeaturesHTMLData, updateLinkedItemApps } from '../../helpers/utils.mjs'; +import { DhLevelOption } from '../levelTier.mjs'; export default class DHClass extends BaseDataItem { /** @inheritDoc */ @@ -10,7 +11,8 @@ export default class DHClass extends BaseDataItem { return foundry.utils.mergeObject(super.metadata, { label: 'TYPES.Item.class', type: 'class', - hasDescription: true + hasDescription: true, + hasLevelUpOptions: true }); } @@ -51,7 +53,13 @@ export default class DHClass extends BaseDataItem { }), backgroundQuestions: new fields.ArrayField(new fields.StringField(), { initial: ['', '', ''] }), connections: new fields.ArrayField(new fields.StringField(), { initial: ['', '', ''] }), - isMulticlass: new fields.BooleanField({ initial: false }) + isMulticlass: new fields.BooleanField({ initial: false }), + levelupOptionTiers: new fields.TypedObjectField( + new fields.TypedObjectField(new fields.EmbeddedDataField(DhLevelOption)), + { + initial: { 2: {}, 3: {}, 4: {} } + } + ) }; } diff --git a/module/data/levelData.mjs b/module/data/levelData.mjs index 4f55d9ee9..ac5546c08 100644 --- a/module/data/levelData.mjs +++ b/module/data/levelData.mjs @@ -41,6 +41,7 @@ export default class DhLevelData extends foundry.abstract.DataModel { level: new fields.NumberField({ required: true, integer: true }), optionKey: new fields.StringField({ required: true }), type: new fields.StringField({ required: true, choices: LevelOptionType }), + subType: new fields.StringField({ nullable: true }), checkboxNr: new fields.NumberField({ required: true, integer: true }), value: new fields.NumberField({ integer: true }), minCost: new fields.NumberField({ integer: true }), diff --git a/module/data/levelTier.mjs b/module/data/levelTier.mjs index 2252e4daa..d2a446f22 100644 --- a/module/data/levelTier.mjs +++ b/module/data/levelTier.mjs @@ -43,17 +43,44 @@ class DhLevelTier extends foundry.abstract.DataModel { } } -class DhLevelOption extends foundry.abstract.DataModel { +export class DhLevelOption extends foundry.abstract.DataModel { static defineSchema() { const fields = foundry.data.fields; return { - label: new fields.StringField({ required: true }), - checkboxSelections: new fields.NumberField({ required: true, integer: true, initial: 1 }), - minCost: new fields.NumberField({ required: true, integer: true, initial: 1 }), - type: new fields.StringField({ required: true, choices: LevelOptionType }), - value: new fields.NumberField({ integer: true }), - amount: new fields.NumberField({ integer: true }) + label: new fields.StringField({ + required: true, + label: 'DAGGERHEART.GENERAL.label' + }), + checkboxSelections: new fields.NumberField({ + required: true, + integer: true, + initial: 1, + label: 'DAGGERHEART.CONFIG.LevelupData.checkboxSelections' + }), + minCost: new fields.NumberField({ + required: true, + integer: true, + initial: 1, + label: 'DAGGERHEART.CONFIG.LevelupData.minCost' + }), + type: new fields.StringField({ + required: true, + choices: LevelOptionType, + label: 'DAGGERHEART.GENERAL.type' + }), + subType: new fields.StringField({ + nullable: true, + label: 'DAGGERHEART.GENERAL.subType' + }), + value: new fields.NumberField({ + integer: true, + label: 'DAGGERHEART.GENERAL.value' + }), + amount: new fields.NumberField({ + integer: true, + label: 'DAGGERHEART.GENERAL.amount' + }) }; } } @@ -162,6 +189,16 @@ export const LevelOptionType = { id: 'multiclass', label: 'Multiclass' }, + dice: { + id: 'dice', + label: 'Increase Dice Size', + subTypes: { + hopeIndex: { key: 'hopeIndex', label: 'DAGGERHEART.GENERAL.hope' }, + fearIndex: { key: 'fearIndex', label: 'DAGGERHEART.GENERAL.fear' }, + advantageIndex: { key: 'advantageIndex', label: 'DAGGERHEART.GENERAL.Advantage.full' }, + comboDieIndex: { key: 'comboDieIndex', label: 'Combo Die' } // Translation pending actual useage + } + }, ...CompanionLevelOptionType }; diff --git a/module/data/levelup.mjs b/module/data/levelup.mjs index 4dc1c058b..dbec711fa 100644 --- a/module/data/levelup.mjs +++ b/module/data/levelup.mjs @@ -90,6 +90,7 @@ export class DhLevelup extends foundry.abstract.DataModel { checkboxSelections: new fields.NumberField({ required: true, integer: true }), minCost: new fields.NumberField({ required: true, integer: true }), type: new fields.StringField({ required: true, choices: LevelOptionType }), + subType: new fields.StringField({ nullable: true }), value: new fields.NumberField({ integer: true }), amount: new fields.NumberField({ integer: true }) }) @@ -242,7 +243,7 @@ export class DhLevelup extends foundry.abstract.DataModel { const checkboxes = [...Array(option.checkboxSelections).keys()].flatMap(index => { const checkboxNr = index + 1; const checkboxData = selections[tierKey]?.[optionKey]?.[checkboxNr]; - const checkbox = { ...option, checkboxNr, tier: tierKey }; + const checkbox = { ...option, checkboxNr, tier: tierKey, option: optionKey }; if (checkboxData) { checkbox.level = checkboxData.level; @@ -343,7 +344,8 @@ export class DhLevelupLevel extends foundry.abstract.DataModel { value: new fields.StringField(), data: new fields.ArrayField(new fields.StringField()), secondaryData: new fields.TypedObjectField(new fields.StringField()), - type: new fields.StringField({ required: true }) + type: new fields.StringField({ required: true }), + subType: new fields.StringField({ nullable: true }) }) ) ) diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index 5e03a680e..ae50d307d 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -11,9 +11,7 @@ export default class DualityRoll extends D20Roll { this.rallyChoices = this.setRallyChoices(); this.guaranteedCritical = options.guaranteedCritical; - const advantageFaces = data.rules?.roll?.defaultAdvantageDice - ? Number.parseInt(data.rules.roll.defaultAdvantageDice) - : 6; + const advantageFaces = data.rules?.roll?.advantageFaces ? Number.parseInt(data.rules.roll.advantageFaces) : 6; this.advantageFaces = Number.isNaN(advantageFaces) ? 6 : advantageFaces; } @@ -139,11 +137,11 @@ export default class DualityRoll extends D20Roll { } this.terms[0] = new game.system.api.dice.diceTypes.HopeDie({ - faces: this.data.rules.dualityRoll?.defaultHopeDice ?? 12 + faces: this.data.rules.roll?.hopeFaces ?? 12 }); this.terms[1] = new foundry.dice.terms.OperatorTerm({ operator: '+' }); this.terms[2] = new game.system.api.dice.diceTypes.FearDie({ - faces: this.data.rules.dualityRoll?.defaultFearDice ?? 12 + faces: this.data.rules.roll?.fearFaces ?? 12 }); } diff --git a/module/systemRegistration/handlebars.mjs b/module/systemRegistration/handlebars.mjs index 1b08e0ad3..527750192 100644 --- a/module/systemRegistration/handlebars.mjs +++ b/module/systemRegistration/handlebars.mjs @@ -52,6 +52,7 @@ export const preloadHandlebarsTemplates = async function () { 'systems/daggerheart/templates/ui/itemBrowser/itemContainer.hbs', 'systems/daggerheart/templates/scene/dh-config.hbs', 'systems/daggerheart/templates/settings/appearance-settings/diceSoNiceTab.hbs', - 'systems/daggerheart/templates/sheets/activeEffect/typeChanges/armorChange.hbs' + 'systems/daggerheart/templates/sheets/activeEffect/typeChanges/armorChange.hbs', + 'systems/daggerheart/templates/dialogs/levelupOptionsDialog/parts/tier.hbs' ]); }; diff --git a/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json b/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json index 6468c1aa6..ec2d4b8d9 100644 --- a/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json +++ b/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json @@ -364,8 +364,8 @@ }, "changes": [ { - "key": "system.rules.dualityRoll.defaultHopeDice", - "value": "d8", + "key": "system.rules.roll.hopeIndex", + "value": 2, "priority": null, "type": "override" } diff --git a/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json b/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json index 0bc6bf2d9..cf5905be9 100644 --- a/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json +++ b/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json @@ -327,8 +327,8 @@ }, "changes": [ { - "key": "system.rules.dualityRoll.defaultFearDice", - "value": "d20", + "key": "system.rules.roll.fearIndex", + "value": 5, "priority": null, "type": "override" } diff --git a/src/packs/environments/environment_Cult_Ritual_QAXXiOKBDmCTauHD.json b/src/packs/environments/environment_Cult_Ritual_QAXXiOKBDmCTauHD.json index 1295db59b..478a19de1 100644 --- a/src/packs/environments/environment_Cult_Ritual_QAXXiOKBDmCTauHD.json +++ b/src/packs/environments/environment_Cult_Ritual_QAXXiOKBDmCTauHD.json @@ -192,9 +192,9 @@ }, "changes": [ { - "key": "system.rules.dualityRoll.defaultHopeDice", + "key": "system.rules.roll.hopeIndex", "mode": 5, - "value": "d10", + "value": 3, "priority": null } ], diff --git a/styles/less/dialog/index.less b/styles/less/dialog/index.less index 947142fff..80e358afa 100644 --- a/styles/less/dialog/index.less +++ b/styles/less/dialog/index.less @@ -51,3 +51,4 @@ @import './character-reset/sheet.less'; @import './compendiumBrowserPackDialog/sheet.less'; +@import './levelup-options-dialog/sheet.less'; \ No newline at end of file diff --git a/styles/less/dialog/levelup-options-dialog/sheet.less b/styles/less/dialog/levelup-options-dialog/sheet.less new file mode 100644 index 000000000..2b6886ed9 --- /dev/null +++ b/styles/less/dialog/levelup-options-dialog/sheet.less @@ -0,0 +1,32 @@ +.daggerheart.dh-style.dialog.levelup-options-dialog { + .dialog-title { + font-size: var(--font-size-32); + color: light-dark(@dark-blue, @golden); + text-align: center; + } + + .tier-tools { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 8px; + + button { + white-space: nowrap; + } + } + + .tier-container { + padding: 0 4px; + display: flex; + flex-direction: column; + gap: 8px; + + .tier-title { + font-size: var(--font-size-18); + color: light-dark(@dark-blue, @golden); + margin-left: auto; + margin-right: auto; + } + } +} \ No newline at end of file diff --git a/templates/dialogs/levelupOptionsDialog/header.hbs b/templates/dialogs/levelupOptionsDialog/header.hbs new file mode 100644 index 000000000..2ea61486a --- /dev/null +++ b/templates/dialogs/levelupOptionsDialog/header.hbs @@ -0,0 +1,3 @@ +
+
{{localize "Tiers"}}
+
\ No newline at end of file diff --git a/templates/dialogs/levelupOptionsDialog/parts/tier.hbs b/templates/dialogs/levelupOptionsDialog/parts/tier.hbs new file mode 100644 index 000000000..f8f4cbabf --- /dev/null +++ b/templates/dialogs/levelupOptionsDialog/parts/tier.hbs @@ -0,0 +1,29 @@ +
+
+ + +
+ {{#with (lookup levelupOptionTiers tab.tier)}} + {{#unless (empty this)}} + {{#each this as |option key|}} +
+ + +
+ {{formGroup @root.fields.label value=option.label name=(concat "system.levelupOptionTiers." ../../tab.tier "." key ".label") localize=true }} + {{formGroup @root.fields.type value=option.type name=(concat "system.levelupOptionTiers." ../../tab.tier "." key ".type") localize=true }} +
+ {{formGroup @root.fields.checkboxSelections value=option.checkboxSelections name=(concat "system.levelupOptionTiers." ../../tab.tier "." key ".checkboxSelections") localize=true }} + {{formGroup @root.fields.minCost value=option.minCost name=(concat "system.levelupOptionTiers." ../../tab.tier "." key ".minCost") localize=true }} + {{#if option.typeData}} + {{formGroup @root.fields.subType value=option.subType name=(concat "system.levelupOptionTiers." ../../tab.tier "." key ".subType") choices=option.typeData.subTypes localize=true }} + {{/if}} +
+
+
+ {{/each}} + {{/unless}} + {{/with}} +
\ No newline at end of file diff --git a/templates/dialogs/levelupOptionsDialog/tiers.hbs b/templates/dialogs/levelupOptionsDialog/tiers.hbs new file mode 100644 index 000000000..aa2eb443c --- /dev/null +++ b/templates/dialogs/levelupOptionsDialog/tiers.hbs @@ -0,0 +1,5 @@ +
+ {{> "systems/daggerheart/templates/dialogs/levelupOptionsDialog/parts/tier.hbs" tab=tabs.tier2}} + {{> "systems/daggerheart/templates/dialogs/levelupOptionsDialog/parts/tier.hbs" tab=tabs.tier3}} + {{> "systems/daggerheart/templates/dialogs/levelupOptionsDialog/parts/tier.hbs" tab=tabs.tier4}} +
\ No newline at end of file diff --git a/templates/levelup/tabs/advancements.hbs b/templates/levelup/tabs/advancements.hbs index 5e65be346..f1b197b52 100644 --- a/templates/levelup/tabs/advancements.hbs +++ b/templates/levelup/tabs/advancements.hbs @@ -19,12 +19,13 @@ type="checkbox" class="selection-checkbox{{#if (gt this.cost 1)}} multi{{/if}}" {{checked this.selected}} {{#if this.disabled}}disabled{{/if}} data-tier="{{this.tier}}" data-level="{{this.level}}" - data-option="{{this.type}}" + data-option="{{this.option}}" data-checkbox-nr="{{this.checkboxNr}}" data-cost="{{this.minCost}}" data-amount="{{this.amount}}" data-value="{{this.value}}" data-type="{{this.type}}" + data-sub-type="{{this.subType}}" /> {{/each}}