diff --git a/lang/en.json b/lang/en.json index efe04425..e5163d42 100755 --- a/lang/en.json +++ b/lang/en.json @@ -2013,6 +2013,10 @@ "gm": { "label": "GM" }, "players": { "label": "Players" } }, + "levelupAuto": { + "label": "Levelup Automation", + "hint": "When you've made your choices and finish levelup, the numerical changes are automatically applied to your character." + }, "actionPoints": { "label": "Action Points", "hint": "Automatically give and take Action Points as combatants take their turns." diff --git a/module/applications/levelup/levelup.mjs b/module/applications/levelup/levelup.mjs index 7820c267..f025c131 100644 --- a/module/applications/levelup/levelup.mjs +++ b/module/applications/levelup/levelup.mjs @@ -46,7 +46,8 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2) tabs: { template: 'systems/daggerheart/templates/levelup/tabs/tab-navigation.hbs' }, advancements: { template: 'systems/daggerheart/templates/levelup/tabs/advancements.hbs' }, selections: { template: 'systems/daggerheart/templates/levelup/tabs/selections.hbs' }, - summary: { template: 'systems/daggerheart/templates/levelup/tabs/summary.hbs' } + summary: { template: 'systems/daggerheart/templates/levelup/tabs/summary.hbs' }, + footer: { template: 'systems/daggerheart/templates/levelup/tabs/footer.hbs' } }; static TABS = { @@ -95,6 +96,7 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2) const context = await super._prepareContext(_options); context.levelup = this.levelup; context.tabs = this._getTabs(this.constructor.TABS); + context.levelupAuto = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).levelupAuto; return context; } diff --git a/module/applications/sheets-configs/character-settings.mjs b/module/applications/sheets-configs/character-settings.mjs new file mode 100644 index 00000000..13ef29c3 --- /dev/null +++ b/module/applications/sheets-configs/character-settings.mjs @@ -0,0 +1,50 @@ +import DHBaseActorSettings from '../sheets/api/actor-setting.mjs'; + +/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ + +export default class DHCharacterSettings extends DHBaseActorSettings { + /**@inheritdoc */ + static DEFAULT_OPTIONS = { + classes: ['character-settings'], + position: { width: 455, height: 'auto' }, + actions: {}, + dragDrop: [ + { dragSelector: null, dropSelector: '.tab.features' }, + { dragSelector: '.feature-item', dropSelector: null } + ] + }; + + /**@override */ + static PARTS = { + header: { + id: 'header', + template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/header.hbs' + }, + tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, + details: { + id: 'details', + template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/details.hbs' + }, + attack: { + id: 'attack', + template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/attack.hbs' + }, + experiences: { + id: 'experiences', + template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/experiences.hbs' + }, + features: { + id: 'features', + template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/features.hbs' + } + }; + + /** @override */ + static TABS = { + primary: { + tabs: [{ id: 'details' }, { id: 'attack' }, { id: 'experiences' }, { id: 'features' }], + initial: 'details', + labelPrefix: 'DAGGERHEART.GENERAL.Tabs' + } + }; +} diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index 6bbef5b0..e00ec843 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -25,6 +25,7 @@ export default class CharacterSheet extends DHBaseActorSheet { toggleEquipItem: CharacterSheet.#toggleEquipItem, toggleResourceDice: CharacterSheet.#toggleResourceDice, handleResourceDice: CharacterSheet.#handleResourceDice, + openConfig: CharacterSheet.#openConfig, useDowntime: this.useDowntime }, window: { @@ -716,6 +717,16 @@ export default class CharacterSheet extends DHBaseActorSheet { }); } + /** + * Open the character config sheet. + * @type {ApplicationClickAction} + */ + static async #openConfig() {} + + /** + * Open the downtime application. + * @type {ApplicationClickAction} + */ static useDowntime(_, button) { new game.system.api.applications.dialogs.Downtime(this.document, button.dataset.type === 'shortRest').render( true diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 2e7d2507..e39f4ae5 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -511,37 +511,39 @@ export default class DhCharacter extends BaseDataActor { : Object.values(game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers).find( tier => currentLevel >= tier.levels.start && currentLevel <= tier.levels.end ).tier; - for (let levelKey in this.levelData.levelups) { - const level = this.levelData.levelups[levelKey]; + if (game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).levelupAuto) { + for (let levelKey in this.levelData.levelups) { + const level = this.levelData.levelups[levelKey]; - this.proficiency += level.achievements.proficiency; + this.proficiency += level.achievements.proficiency; - for (let selection of level.selections) { - switch (selection.type) { - case 'trait': - selection.data.forEach(data => { - this.traits[data].value += 1; - this.traits[data].tierMarked = selection.tier === currentTier; - }); - break; - case 'hitPoint': - this.resources.hitPoints.max += selection.value; - break; - case 'stress': - this.resources.stress.max += selection.value; - break; - case 'evasion': - this.evasion += selection.value; - break; - case 'proficiency': - this.proficiency += selection.value; - break; - case 'experience': - Object.keys(this.experiences).forEach(key => { - const experience = this.experiences[key]; - experience.value += selection.value; - }); - break; + for (let selection of level.selections) { + switch (selection.type) { + case 'trait': + selection.data.forEach(data => { + this.traits[data].value += 1; + this.traits[data].tierMarked = selection.tier === currentTier; + }); + break; + case 'hitPoint': + this.resources.hitPoints.max += selection.value; + break; + case 'stress': + this.resources.stress.max += selection.value; + break; + case 'evasion': + this.evasion += selection.value; + break; + case 'proficiency': + this.proficiency += selection.value; + break; + case 'experience': + Object.keys(this.experiences).forEach(key => { + const experience = this.experiences[key]; + experience.value += selection.value; + }); + break; + } } } } diff --git a/module/data/settings/Automation.mjs b/module/data/settings/Automation.mjs index d4d6a2a7..66e685d0 100644 --- a/module/data/settings/Automation.mjs +++ b/module/data/settings/Automation.mjs @@ -14,6 +14,11 @@ export default class DhAutomation extends foundry.abstract.DataModel { label: 'DAGGERHEART.SETTINGS.Automation.FIELDS.hopeFear.players.label' }) }), + levelupAuto: new fields.BooleanField({ + required: true, + initial: true, + label: 'DAGGERHEART.SETTINGS.Automation.FIELDS.levelupAuto.label' + }), actionPoints: new fields.BooleanField({ required: true, initial: false, diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index d7760637..dad36ec7 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -172,26 +172,30 @@ export default class DhpActor extends Actor { } async levelUp(levelupData) { + const levelupAuto = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).levelupAuto; + const levelups = {}; for (var levelKey of Object.keys(levelupData)) { const level = levelupData[levelKey]; - for (var experienceKey in level.achievements.experiences) { - const experience = level.achievements.experiences[experienceKey]; - await this.update({ - [`system.experiences.${experienceKey}`]: { - name: experience.name, - value: experience.modifier - } - }); - - if (this.system.companion) { - await this.system.companion.update({ + if (levelupAuto) { + for (var experienceKey in level.achievements.experiences) { + const experience = level.achievements.experiences[experienceKey]; + await this.update({ [`system.experiences.${experienceKey}`]: { - name: '', + name: experience.name, value: experience.modifier } }); + + if (this.system.companion) { + await this.system.companion.update({ + [`system.experiences.${experienceKey}`]: { + name: '', + value: experience.modifier + } + }); + } } } @@ -250,74 +254,86 @@ export default class DhpActor extends Actor { } for (var addition of featureAdditions) { - for (var featureData of addition.features) { - const feature = new DHFeature({ - ...featureData, - description: game.i18n.localize(featureData.description) - }); - - const document = featureData.toPartner && this.system.partner ? this.system.partner : this; - const embeddedItem = await document.createEmbeddedDocuments('Item', [ - { + if (levelupAuto) { + for (var featureData of addition.features) { + const feature = new DHFeature({ ...featureData, - name: game.i18n.localize(featureData.name), - type: 'feature', - system: feature - } - ]); - const newFeature = { - onPartner: Boolean(featureData.toPartner && this.system.partner), - id: embeddedItem[0].id - }; - addition.checkbox.features = !addition.checkbox.features - ? [newFeature] - : [...addition.checkbox.features, newFeature]; + description: game.i18n.localize(featureData.description) + }); + + const document = featureData.toPartner && this.system.partner ? this.system.partner : this; + const embeddedItem = await document.createEmbeddedDocuments('Item', [ + { + ...featureData, + name: game.i18n.localize(featureData.name), + type: 'feature', + system: feature + } + ]); + const newFeature = { + onPartner: Boolean(featureData.toPartner && this.system.partner), + id: embeddedItem[0].id + }; + addition.checkbox.features = !addition.checkbox.features + ? [newFeature] + : [...addition.checkbox.features, newFeature]; + } } selections.push(addition.checkbox); } if (multiclass) { - const subclassItem = await foundry.utils.fromUuid(multiclass.secondaryData.subclass); - const subclassData = subclassItem.toObject(); - const multiclassItem = await foundry.utils.fromUuid(multiclass.data[0]); - const multiclassData = multiclassItem.toObject(); + if (levelupAuto) { + const subclassItem = await foundry.utils.fromUuid(multiclass.secondaryData.subclass); + const subclassData = subclassItem.toObject(); + const multiclassItem = await foundry.utils.fromUuid(multiclass.data[0]); + const multiclassData = multiclassItem.toObject(); - const embeddedItem = await this.createEmbeddedDocuments('Item', [ - { - ...multiclassData, - system: { - ...multiclassData.system, - domains: [multiclass.secondaryData.domain], - isMulticlass: true + const embeddedItem = await this.createEmbeddedDocuments('Item', [ + { + ...multiclassData, + system: { + ...multiclassData.system, + domains: [multiclass.secondaryData.domain], + isMulticlass: true + } } - } - ]); + ]); - await this.createEmbeddedDocuments('Item', [ - { - ...subclassData, - system: { - ...subclassData.system, - isMulticlass: true + await this.createEmbeddedDocuments('Item', [ + { + ...subclassData, + system: { + ...subclassData.system, + isMulticlass: true + } } - } - ]); - selections.push({ ...multiclass, itemUuid: embeddedItem[0].uuid }); + ]); + selections.push({ ...multiclass, itemUuid: embeddedItem[0].uuid }); + } else { + selections.push({ ...multiclass }); + } } for (var domainCard of domainCards) { - const item = await foundry.utils.fromUuid(domainCard.data[0]); - const embeddedItem = await this.createEmbeddedDocuments('Item', [item.toObject()]); - selections.push({ ...domainCard, itemUuid: embeddedItem[0].uuid }); + if (levelupAuto) { + const item = await foundry.utils.fromUuid(domainCard.data[0]); + const embeddedItem = await this.createEmbeddedDocuments('Item', [item.toObject()]); + selections.push({ ...domainCard, itemUuid: embeddedItem[0].uuid }); + } else { + selections.push({ ...domainCard }); + } } const achievementDomainCards = []; - for (var card of Object.values(level.achievements.domainCards)) { - const item = await foundry.utils.fromUuid(card.uuid); - const embeddedItem = await this.createEmbeddedDocuments('Item', [item.toObject()]); - card.itemUuid = embeddedItem[0].uuid; - achievementDomainCards.push(card); + if (levelupAuto) { + for (var card of Object.values(level.achievements.domainCards)) { + const item = await foundry.utils.fromUuid(card.uuid); + const embeddedItem = await this.createEmbeddedDocuments('Item', [item.toObject()]); + card.itemUuid = embeddedItem[0].uuid; + achievementDomainCards.push(card); + } } if (subclassFeatureState.class) { diff --git a/styles/less/dialog/level-up/selections-container.less b/styles/less/dialog/level-up/selections-container.less index 10d61ed6..552f7c86 100644 --- a/styles/less/dialog/level-up/selections-container.less +++ b/styles/less/dialog/level-up/selections-container.less @@ -104,4 +104,10 @@ } } } + + .levelup-footer { + display: flex; + gap: 8px; + margin-top: 8px; + } } diff --git a/templates/levelup/tabs/footer.hbs b/templates/levelup/tabs/footer.hbs new file mode 100644 index 00000000..85c49a91 --- /dev/null +++ b/templates/levelup/tabs/footer.hbs @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/templates/levelup/tabs/tab-navigation.hbs b/templates/levelup/tabs/tab-navigation.hbs index 82aacf1e..990e909d 100644 --- a/templates/levelup/tabs/tab-navigation.hbs +++ b/templates/levelup/tabs/tab-navigation.hbs @@ -1,40 +1,44 @@
- -
- {{#if this.showTabs}} - - {{/if}} -
- {{#if this.navigate.previous.fromSummary}} - - {{else}} - {{#if (not this.navigate.previous.disabled)}} - - {{/if}} + {{#if levelupAuto}} + +
+ {{#if this.showTabs}} + {{/if}} - {{#if this.navigate.next.show}} - {{#if this.navigate.next.toSummary}} - - {{else}} - - {{/if}} - {{else}} -
+ {{#if this.levelupAuto}} +
+ {{#if this.navigate.previous.fromSummary}} + + {{else}} + {{#if (not this.navigate.previous.disabled)}} + + {{/if}} + {{/if}} + {{#if this.navigate.next.show}} + {{#if this.navigate.next.toSummary}} + + {{else}} + + {{/if}} + {{else}} +
+ {{/if}} +
{{/if}}
-
- + + {{/if}}
\ No newline at end of file diff --git a/templates/settings/automation-settings.hbs b/templates/settings/automation-settings.hbs index a02d6f97..efc25221 100644 --- a/templates/settings/automation-settings.hbs +++ b/templates/settings/automation-settings.hbs @@ -11,6 +11,7 @@ {{formGroup settingFields.schema.fields.actionPoints value=settingFields._source.actionPoints localize=true}} {{formGroup settingFields.schema.fields.hordeDamage value=settingFields._source.hordeDamage localize=true}} {{formGroup settingFields.schema.fields.effects.fields.rangeDependent value=settingFields._source.effects.rangeDependent localize=true}} + {{formGroup settingFields.schema.fields.levelupAuto value=settingFields._source.levelupAuto localize=true}}