diff --git a/lang/en.json b/lang/en.json index 3eea7444..881ad4e8 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1275,6 +1275,13 @@ "diceValue": "Dice Value", "die": "Die" }, + "OutcomeType": { + "successHope": "Success/ Hope", + "successFear": "Success/ Fear", + "failureHope": "Failure/ Hope", + "failureFear": "Failure/ Fear", + "simpleOutcome": "Outcome" + }, "Range": { "self": { "name": "Self", diff --git a/module/applications/sheets-configs/action-base-config.mjs b/module/applications/sheets-configs/action-base-config.mjs index 51243f39..88c6d343 100644 --- a/module/applications/sheets-configs/action-base-config.mjs +++ b/module/applications/sheets-configs/action-base-config.mjs @@ -10,12 +10,87 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) this.action = action; this.openSection = null; this.openTrigger = this.action.triggers.length > 0 ? 0 : null; + + this.outcomeTabs = DHActionBaseConfig.getOutcomeTabs(action); } get title() { return `${game.i18n.localize('DAGGERHEART.GENERAL.Tabs.settings')}: ${this.action.name}`; } + /* Needs to consider effect altOutcomes aswell */ + static getOutcomeTabs(action) { + const outcomeKeys = [ + 'successHope', + ...Object.keys(action.damage?.altOutcomes ?? {}).filter(key => action.damage.altOutcomes[key]) + ]; + return outcomeKeys.reduce((acc, key, index) => { + acc[key] = { + active: index === 0, + cssClass: '', + group: 'outcomes', + id: key, + icon: null, + label: + outcomeKeys.length === 1 + ? game.i18n.localize('DAGGERHEART.CONFIG.OutcomeType.simpleOutcome') + : game.i18n.localize(CONFIG.DH.ACTIONS.outcomeTypes[key].label) + }; + return acc; + }, {}); + } + + /* Needs to consider effect altOutcomes aswell */ + static selectOutcome(action, callback) { + const choices = Object.entries(CONFIG.DH.ACTIONS.outcomeTypes).reduce((acc, [key, value]) => { + if (key !== 'successHope' && action.damage.altOutcomes[key] === null) + acc.push({ id: key, label: game.i18n.localize(value.label) }); + + return acc; + }, []); + const content = new foundry.data.fields.StringField({ + label: game.i18n.localize('Outcome'), + choices, + required: true + }).toFormGroup( + {}, + { + name: 'outcome', + localize: true, + nameAttr: 'value', + labelAttr: 'label' + } + ).outerHTML; + + const callbackWrapper = (_, button) => { + const choiceIndex = button.form.elements.outcome.value; + callback(choices[choiceIndex]?.id); + }; + + const typeDialog = new foundry.applications.api.DialogV2({ + buttons: [ + foundry.utils.mergeObject( + { + action: 'ok', + label: 'Confirm', + icon: 'fas fa-check', + default: true + }, + { callback: callbackWrapper } + ) + ], + content: content, + rejectClose: false, + modal: false, + window: { + title: game.i18n.localize('Add Outcome') + }, + position: { width: 300 } + }); + + typeDialog.render(true); + } + static DEFAULT_OPTIONS = { tag: 'form', classes: ['daggerheart', 'dh-style', 'action-config', 'dialog', 'max-800'], @@ -31,6 +106,8 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) addElement: this.addElement, removeElement: this.removeElement, removeTransformActor: this.removeTransformActor, + addOutcome: this.addOutcome, + removeOutcome: this.removeOutcome, editEffect: this.editEffect, addDamage: this.addDamage, removeDamage: this.removeDamage, @@ -120,25 +197,6 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) } }; - static OUTCOME_TABS = { - successHope: { - active: true, - cssClass: '', - group: 'outcomes', - id: 'successHope', - icon: null, - label: 'Success With Hope' - }, - successFear: { - active: false, - cssClass: '', - group: 'outcomes', - id: 'successFear', - icon: null, - label: 'Success With Fear' - }, - }; - static CLEAN_ARRAYS = ['cost', 'effects', 'summon']; _getTabs(tabs) { @@ -187,8 +245,9 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) context.openSection = this.openSection; context.tabs = this._getTabs(this.constructor.TABS); - - context.outcomeTabs = this._getTabs(this.constructor.OUTCOME_TABS); + + context.outcomeTabs = this._getTabs(this.outcomeTabs); + context.allOutcomesAssigned = Object.keys(this.outcomeTabs).length >= 4; context.config = CONFIG.DH; if (this.action.damage) { @@ -338,7 +397,11 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) if (!this.action.damage.parts) return; const outcome = button.dataset.outcome; - const choices = getUnusedDamageTypes(this.action._source.damage.parts); + const outcomeParts = + outcome === 'successHope' + ? this.action._source.damage.parts + : this.action._source.damage.altOutcomes[outcome].parts; + const choices = getUnusedDamageTypes(outcomeParts); const content = new foundry.data.fields.StringField({ label: game.i18n.localize('Damage Type'), choices, @@ -361,8 +424,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) if (type === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) part.type = this.action.schema.fields.damage.fields.parts.element.fields.type.element.initial; - if (outcome === 'successHope') - data.damage.parts[type] = part; + if (outcome === 'successHope') data.damage.parts[type] = part; else { if (!data.damage.altOutcomes[outcome]) { data.damage.altOutcomes[outcome] = new AltDamageOutcome(); @@ -401,9 +463,15 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) static removeDamage(_event, button) { if (!this.action.damage.parts) return; const data = this.action.toObject(); - const key = button.dataset.key; - delete data.damage.parts[key]; - data.damage.parts[`${key}`] = _del; + const { key, outcome } = button.dataset; + if (outcome === 'successHope') { + delete data.damage.parts[key]; + data.damage.parts[`${key}`] = _del; + } else { + delete data.damage.altOutcomes[outcome].parts[key]; + data.damage.altOutcomes[outcome].parts[`${key}`] = _del; + } + this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); } @@ -494,6 +562,8 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) } /** Specific implementation in extending classes **/ + static addOutcome(_event) {} + static removeOutcome(_event) {} static async addEffect(_event) {} static removeEffect(_event, _button) {} static editEffect(_event) {} diff --git a/module/applications/sheets-configs/action-config.mjs b/module/applications/sheets-configs/action-config.mjs index ef529e9b..833c3ebd 100644 --- a/module/applications/sheets-configs/action-config.mjs +++ b/module/applications/sheets-configs/action-config.mjs @@ -1,3 +1,4 @@ +import { AltDamageOutcome } from '../../data/fields/action/damageField.mjs'; import DHActionBaseConfig from './action-base-config.mjs'; export default class DHActionConfig extends DHActionBaseConfig { @@ -5,6 +6,8 @@ export default class DHActionConfig extends DHActionBaseConfig { ...DHActionBaseConfig.DEFAULT_OPTIONS, actions: { ...DHActionBaseConfig.DEFAULT_OPTIONS.actions, + addOutcome: this.addOutcome, + removeOutcome: this.removeOutcome, addEffect: this.addEffect, removeEffect: this.removeEffect, editEffect: this.editEffect @@ -19,6 +22,28 @@ export default class DHActionConfig extends DHActionBaseConfig { return context; } + static addOutcome() { + const data = this.action.toObject(); + + DHActionBaseConfig.selectOutcome(this.action, key => { + if (!key) return; + + data.damage.altOutcomes[key] = new AltDamageOutcome(); + this.outcomeTabs = DHActionBaseConfig.getOutcomeTabs(data); + this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); + }); + } + + static removeOutcome(_event, button) { + const { outcome } = button.dataset; + const data = this.action.toObject(); + + data.damage.altOutcomes[outcome] = null; + this.outcomeTabs = DHActionBaseConfig.getOutcomeTabs(data); + + this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); + } + static async addEffect(event) { const { areaIndex } = event.target.dataset; if (!this.action.effects) return; diff --git a/module/config/actionConfig.mjs b/module/config/actionConfig.mjs index a6c04e18..012ca4c6 100644 --- a/module/config/actionConfig.mjs +++ b/module/config/actionConfig.mjs @@ -122,3 +122,22 @@ export const areaTypes = { label: 'Placed Area' } }; + +export const outcomeTypes = { + successHope: { + key: 'successHope', + label: 'DAGGERHEART.CONFIG.OutcomeType.successHope' + }, + successFear: { + key: 'successFear', + label: 'DAGGERHEART.CONFIG.OutcomeType.successFear' + }, + failureHope: { + key: 'failureHope', + label: 'DAGGERHEART.CONFIG.OutcomeType.failureHope' + }, + failureFear: { + key: 'failureFear', + label: 'DAGGERHEART.CONFIG.OutcomeType.failureFear' + } +}; diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index 6c0d2a88..6da3f188 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -10,7 +10,7 @@ const getDamageBaseFields = () => ({ initial: false, label: 'DAGGERHEART.ACTIONS.Settings.includeBase.label' }), - direct: new fields.BooleanField({ initial: false, label: 'DAGGERHEART.CONFIG.DamageType.direct.name' }), + direct: new fields.BooleanField({ initial: false, label: 'DAGGERHEART.CONFIG.DamageType.direct.name' }) }); export default class DamageField extends fields.SchemaField { @@ -26,8 +26,7 @@ export default class DamageField extends fields.SchemaField { altOutcomes: new fields.SchemaField({ successFear: new fields.EmbeddedDataField(AltDamageOutcome, { nullable: true, initial: null }), failureHope: new fields.EmbeddedDataField(AltDamageOutcome, { nullable: true, initial: null }), - failureFear: new fields.EmbeddedDataField(AltDamageOutcome, { nullable: true, initial: null }), - critical: new fields.EmbeddedDataField(AltDamageOutcome, { nullable: true, initial: null }) + failureFear: new fields.EmbeddedDataField(AltDamageOutcome, { nullable: true, initial: null }) }), groupAttack: new fields.StringField({ choices: CONFIG.DH.GENERAL.groupAttackRange, @@ -347,14 +346,14 @@ export class AltDamageOutcome extends foundry.abstract.DataModel { static defineSchema() { return { useStandardHitPointDamage: new fields.BooleanField({ required: true, initial: true }), - ...getDamageBaseFields(), - } + ...getDamageBaseFields() + }; } get data() { return { ...this.parent, - ...this, - } + ...this + }; } -} \ No newline at end of file +} diff --git a/templates/actionTypes/damage.hbs b/templates/actionTypes/damage.hbs index f1952c78..fef6591e 100644 --- a/templates/actionTypes/damage.hbs +++ b/templates/actionTypes/damage.hbs @@ -10,13 +10,13 @@