diff --git a/src/module/data/specialAbility.mjs b/src/module/data/specialAbility.mjs index 8341214b..e49ad641 100644 --- a/src/module/data/specialAbility.mjs +++ b/src/module/data/specialAbility.mjs @@ -71,11 +71,11 @@ export class SpecialAbilityDataModel extends BaseItem { } } - isActive(options) { // TODO also handle Waffenlimit + isActive(options) { const requirements = this.#getRequirements() - let passes = false + let passes = true let mod = 0 const flatActor = foundry.utils.flattenObject(this.parent.actor.system) @@ -89,13 +89,18 @@ export class SpecialAbilityDataModel extends BaseItem { if (requirement.talent) { targetField = this.parent.actor.itemTypes["Skill"].find(p => p.name.toLocaleLowerCase() === requirement.talent.toLocaleLowerCase()).taw } - if (requirement.minValue) { - passes = targetField >= requirement.minValue - } else if (requirement.maxValue) { - passes = targetField <= requirement.maxValue + passes = requirement.minValue <= targetField + if (!passes) console.log(`fails requirement ${requirement.attribute ?? requirement.talent} (${requirement.minValue} <= ${targetField})`) + } + if (requirement.maxValue) { + passes = targetField <= requirement.maxValue + if (!passes) console.log(`fails requirement ${requirement.attribute ?? requirement.talent} (${targetField} <= ${requirement.maxValue})`) + } + if (requirement.sonderfertigkeit) { + passes = this.parent.actor.itemTypes["SpecialAbility"].find(p => p.name === requirement.sonderfertigkeit) != undefined + if (!passes) console.log(`fails requirement ${requirement.sonderfertigkeit} (not in possession)`) } - if (requirement["compare"]) { const {ownAttribute, operation, targetAttribute} = requirement["compare"] if (options.target) { @@ -122,29 +127,39 @@ export class SpecialAbilityDataModel extends BaseItem { passes = ourTargetField > foreignTargetField; break; } + if (!passes) { + console.log(`fails compare requirement ${ownAttribute} ${operation} ${targetAttribute}`) + } + } else { + console.log(`fails compare requirement as no target has been selected`) + return false // cant pass as we dont have a target } - passes = false } - if (!passes) { + console.log("fails atleast 1 requirement of ", this) break } } - - if (passes) { // TODO: how are we going to communicate the malus? - this.system.waffenLimit.forEach(waff => { - if (waff.waffe) { - passes = options.weapon.name === waff.waffe - if (waff.mod) mod = waff.mod - } else if (waff.gruppe) { - passes = options.skill.name === waff.gruppe - if (waff.mod) mod = waff.mod + console.log(this.name, "requirements", passes) + if (passes) { + if (options?.weapon) { + for (const waff of this.waffenLimit) { + if (waff.waffe) { + passes = options?.weapon.name === waff.waffe ?? false + if (waff.mod) mod = waff.mod + if (passes) + break + } + if (waff.gruppe) { + passes = options?.skill.name === waff.gruppe ?? false + if (waff.mod) mod = waff.mod + if (passes) + break + } } - - - }) + } } - + console.log("return value", {passes, mod}) return {passes, mod} } } diff --git a/src/module/dialog/combatAction.mjs b/src/module/dialog/combatAction.mjs index 81730f5c..45c44925 100644 --- a/src/module/dialog/combatAction.mjs +++ b/src/module/dialog/combatAction.mjs @@ -18,8 +18,8 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2 classes: ['dsa41', 'dialog', 'combat'], tag: "form", position: { - width: 320, - height: 540 + width: 480, + height: 640 }, window: { resizable: false, @@ -114,7 +114,6 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2 const tokenId = this._actor.getActiveTokens()[0].id const thisTokenRepresentative = tokens.get(tokenId) - /** * * @type {[TokenDistance]} @@ -124,7 +123,7 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2 isSelected: this._targetId === token.id, ...this.#getDistanceBetween(thisTokenRepresentative, token) } - }) + }).sort((a, b) => a.d - b.d).sort((a, b) => (a.isSelected ? 0 : 1) - (b.isSelected ? 0 : 1)) } #evaluateWeapons() { @@ -178,7 +177,7 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2 } }) - this._weapons = weapons + this._weapons = weapons.sort((a, b) => (a.isSelected ? 0 : 1) - (b.isSelected ? 0 : 1)) return this._weapons } @@ -200,9 +199,10 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2 type: action.type, source: action.source, cost: action.cost, + penalty: action.eval?.mod ?? 0, mod: action.mod, } - }) + }).sort((a, b) => (a.isSelected ? 0 : 1) - (b.isSelected ? 0 : 1)) return this._maneuvers } @@ -237,16 +237,25 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2 } - _onRender(context, options) { + #update(context) { const target = this.element.querySelector(".actions button .value") - this.element.querySelectorAll('[name="mod"], [name="malus"]').forEach(e => e.addEventListener('change', (event) => { - - const at = Number(context.targetNumber) - const malus = Number(this.element.querySelector('[name="malus"]').value) - const mod = Number(this.element.querySelector('[name="mod"]').value) - const maneuver = this._maneuvers?.find(p => p.id === this._combatManeuverId) - const result = at + (maneuver.mod?.(mod) ?? 0) + malus + const at = Number(context.targetNumber) + const maneuver = this._maneuvers?.find(p => p.id === this._combatManeuverId) + const mod = Number(this.element.querySelector('[name="mod"]').value) + const penalty = (maneuver?.penalty ?? 0) + (maneuver?.mod?.(mod) ?? 0) ?? 0 + const circumstance = Number(this.element.querySelector('[name="circumstance"]').value) + this.element.querySelector('[name="penalty"]').value = penalty + circumstance + const result = (at + circumstance + penalty) ?? false + if (result) { target.textContent = `(${result})` + } + } + + _onRender(context, options) { + this.#update(context) + + this.element.querySelectorAll('[name="mod"], [name="malus"], [name="circumstance"]').forEach(e => e.addEventListener('change', (event) => { + this.#update(context) })) } diff --git a/src/module/sheets/actions/action-manager.mjs b/src/module/sheets/actions/action-manager.mjs index f2e01d6a..c81ecec0 100644 --- a/src/module/sheets/actions/action-manager.mjs +++ b/src/module/sheets/actions/action-manager.mjs @@ -58,7 +58,14 @@ export class ActionManager { cost: ActionManager.FREE, type: ActionManager.INTERACTION, source: ActionManager.SF, - eval: (options) => this.#hatSonderfertigkeit("Schnellziehen", options) && this.#evalSonderfertigkeitRequirements("Schnellziehen", options) + eval: (options) => { + const step1 = this.#hatSonderfertigkeit("Schnellziehen", options) + const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Schnellziehen", options) + if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) { + return step2WithBenefits + } else + return false + }, } ] @@ -90,7 +97,14 @@ export class ActionManager { type: ActionManager.ATTACK, cost: ActionManager.CONTINUING, source: ActionManager.SF, - eval: (options) => this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Scharfschütze", options) && this.#evalSonderfertigkeitRequirements("Scharfschütze", options), + eval: (options) => { + const step1 = this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Scharfschütze", options) + const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Scharfschütze", options) + if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) { + return step2WithBenefits + } else + return false + }, mod: (value) => -value }, { @@ -105,7 +119,14 @@ export class ActionManager { type: ActionManager.INTERACTION, cost: ActionManager.CONTINUING, source: ActionManager.SF, - eval: (options) => this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Scharfschütze", options) && this.#evalSonderfertigkeitRequirements("Scharfschütze", options) + eval: (options) => { + const step1 = this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Scharfschütze", options) + const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Scharfschütze", options) + if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) { + return step2WithBenefits + } else + return false + } }, { name: "Abwehraktion", @@ -134,11 +155,14 @@ export class ActionManager { cost: ActionManager.REGULAR, source: ActionManager.SF, mod: (value) => value, - eval: (options) => - this.#hatWaffeinHand() && - this.#hatSonderfertigkeit("Finte", options) && - this.#evalSonderfertigkeitRequirements("Finte", options) - + eval: (options) => { + const step1 = this.#hatWaffeinHand() && this.#hatSonderfertigkeit("Finte", options) + const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Finte", options) + if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) { + return step2WithBenefits + } else + return false + } }, { name: "Wuchtschlag", @@ -154,16 +178,28 @@ export class ActionManager { cost: ActionManager.REGULAR, source: ActionManager.SF, mod: (value) => -(value), - eval: (options) => !this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Wuchtschlag", options) - && this.#evalSonderfertigkeitRequirements("Wuchtschlag", options) + eval: (options) => { + const step1 = !this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Wuchtschlag", options) + const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Wuchtschlag", options) + if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) { + return step2WithBenefits + } else + return false + } }, { name: "Betäubungsschlag", type: ActionManager.ATTACK, cost: ActionManager.REGULAR, source: ActionManager.SF, - eval: (options) => !this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Betäubungsschlag", options) - && this.#evalSonderfertigkeitRequirements("Betäubungsschlag", options) + eval: (options) => { + const step1 = !this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Betäubungsschlag", options) + const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Betäubungsschlag", options) + if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) { + return step2WithBenefits + } else + return false + } } ] @@ -201,20 +237,32 @@ export class ActionManager { type: ActionManager.INTERACTION, cost: ActionManager.CONTINUING, source: ActionManager.SF, - eval: (options) => this.#hatMunition() + eval: (options) => { + const step1 = this.#hatMunition() && this.#hatFernkampfWaffeinHand("Bogen", options) && this.#hatSonderfertigkeit("Schnellladen (Bogen)", options) - && this.#evalSonderfertigkeitRequirements("Schnellladen (Bogen)", options) + const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Schnellladen (Bogen)", options) + if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) { + return step2WithBenefits + } else + return false + } }, { name: "Schnellladen (Armbrust)", type: ActionManager.INTERACTION, cost: ActionManager.CONTINUING, source: ActionManager.SF, - eval: (options) => this.#hatMunition() - && this.#hatFernkampfWaffeinHand("Armbrust", options) - && this.#hatSonderfertigkeit("Schnellladen (Armbrust)", options) - && this.#evalSonderfertigkeitRequirements("Schnellladen (Armbrust)", options) + eval: (options) => { + const step1 = this.#hatMunition() + && this.#hatFernkampfWaffeinHand("Armbrust", options) + && this.#hatSonderfertigkeit("Schnellladen (Armbrust)", options) + const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Schnellladen (Armbrust)", options) + if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) { + return step2WithBenefits + } else + return false + } }, { name: "Nachladen", @@ -272,7 +320,7 @@ export class ActionManager { #evalSonderfertigkeitRequirements(nameOfSF, options) { const sf = this.actor.itemTypes["SpecialAbility"].find(p => p.name === nameOfSF) - return sf.system.isActive(options).passes + return sf?.system.isActive(options) ?? false } /** @@ -282,14 +330,15 @@ export class ActionManager { evaluate(options) { let actionArray = [...this.#freeActions, ...this.#regularActions, ...this.#continuingActions] - console.log(this.actor, actionArray.map((action) => { + return actionArray.filter(action => { + console.log(action.name, action.eval(options)) + return action.eval(options) + }).map(action => { return { ...action, eval: action.eval(options) } - })) - const validActions = actionArray.filter(action => action.eval()) - return validActions + }) } } diff --git a/src/style/organisms/_combat-action-dialog.scss b/src/style/organisms/_combat-action-dialog.scss index 0fd892df..0773beaa 100644 --- a/src/style/organisms/_combat-action-dialog.scss +++ b/src/style/organisms/_combat-action-dialog.scss @@ -17,6 +17,7 @@ display: flex; flex-direction: column; height: 100%; + gap: 16px 0; fieldset { @@ -33,6 +34,10 @@ padding: 0 16px; } + &.modding { + flex: 0; + } + } ul { @@ -41,6 +46,10 @@ padding: 0; margin: 0; text-indent: 0; + overflow: hidden; + overflow-y: auto; + margin: 0 -8px; + max-height: 120px; li { @@ -49,7 +58,7 @@ line-height: 32px; vertical-align: middle; - grid-template-columns: 32px 1fr 83px; + grid-template-columns: 32px 1fr 90px; grid-template-rows: 1fr; border: 1px transparent; margin: 8px; @@ -69,9 +78,16 @@ .malus-and-mod { display: grid; - grid-template-columns: 1fr 1fr; + grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 1fr; gap: 0 8px; + + label { + + span { + text-align: center; + } + } } .actions { diff --git a/src/templates/dialog/combat-action.hbs b/src/templates/dialog/combat-action.hbs index 20cda01b..0e39ef4c 100644 --- a/src/templates/dialog/combat-action.hbs +++ b/src/templates/dialog/combat-action.hbs @@ -37,15 +37,18 @@ -