finalises dialog

pull/61/head
macniel 2025-10-22 16:42:07 +02:00
parent 10d05683ad
commit 2b22a8fa6f
5 changed files with 157 additions and 65 deletions

View File

@ -71,11 +71,11 @@ export class SpecialAbilityDataModel extends BaseItem {
} }
} }
isActive(options) { // TODO also handle Waffenlimit isActive(options) {
const requirements = this.#getRequirements() const requirements = this.#getRequirements()
let passes = false let passes = true
let mod = 0 let mod = 0
const flatActor = foundry.utils.flattenObject(this.parent.actor.system) const flatActor = foundry.utils.flattenObject(this.parent.actor.system)
@ -89,13 +89,18 @@ export class SpecialAbilityDataModel extends BaseItem {
if (requirement.talent) { if (requirement.talent) {
targetField = this.parent.actor.itemTypes["Skill"].find(p => p.name.toLocaleLowerCase() === requirement.talent.toLocaleLowerCase()).taw targetField = this.parent.actor.itemTypes["Skill"].find(p => p.name.toLocaleLowerCase() === requirement.talent.toLocaleLowerCase()).taw
} }
if (requirement.minValue) { if (requirement.minValue) {
passes = targetField >= requirement.minValue passes = requirement.minValue <= targetField
} else if (requirement.maxValue) { if (!passes) console.log(`fails requirement ${requirement.attribute ?? requirement.talent} (${requirement.minValue} <= ${targetField})`)
passes = targetField <= requirement.maxValue }
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"]) { if (requirement["compare"]) {
const {ownAttribute, operation, targetAttribute} = requirement["compare"] const {ownAttribute, operation, targetAttribute} = requirement["compare"]
if (options.target) { if (options.target) {
@ -122,29 +127,39 @@ export class SpecialAbilityDataModel extends BaseItem {
passes = ourTargetField > foreignTargetField; passes = ourTargetField > foreignTargetField;
break; 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) { if (!passes) {
console.log("fails atleast 1 requirement of ", this)
break break
} }
} }
console.log(this.name, "requirements", passes)
if (passes) { // TODO: how are we going to communicate the malus? if (passes) {
this.system.waffenLimit.forEach(waff => { if (options?.weapon) {
if (waff.waffe) { for (const waff of this.waffenLimit) {
passes = options.weapon.name === waff.waffe if (waff.waffe) {
if (waff.mod) mod = waff.mod passes = options?.weapon.name === waff.waffe ?? false
} else if (waff.gruppe) { if (waff.mod) mod = waff.mod
passes = options.skill.name === waff.gruppe if (passes)
if (waff.mod) mod = waff.mod 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} return {passes, mod}
} }
} }

View File

@ -18,8 +18,8 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
classes: ['dsa41', 'dialog', 'combat'], classes: ['dsa41', 'dialog', 'combat'],
tag: "form", tag: "form",
position: { position: {
width: 320, width: 480,
height: 540 height: 640
}, },
window: { window: {
resizable: false, resizable: false,
@ -114,7 +114,6 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
const tokenId = this._actor.getActiveTokens()[0].id const tokenId = this._actor.getActiveTokens()[0].id
const thisTokenRepresentative = tokens.get(tokenId) const thisTokenRepresentative = tokens.get(tokenId)
/** /**
* *
* @type {[TokenDistance]} * @type {[TokenDistance]}
@ -124,7 +123,7 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
isSelected: this._targetId === token.id, isSelected: this._targetId === token.id,
...this.#getDistanceBetween(thisTokenRepresentative, token) ...this.#getDistanceBetween(thisTokenRepresentative, token)
} }
}) }).sort((a, b) => a.d - b.d).sort((a, b) => (a.isSelected ? 0 : 1) - (b.isSelected ? 0 : 1))
} }
#evaluateWeapons() { #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 return this._weapons
} }
@ -200,9 +199,10 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
type: action.type, type: action.type,
source: action.source, source: action.source,
cost: action.cost, cost: action.cost,
penalty: action.eval?.mod ?? 0,
mod: action.mod, mod: action.mod,
} }
}) }).sort((a, b) => (a.isSelected ? 0 : 1) - (b.isSelected ? 0 : 1))
return this._maneuvers 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") 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 maneuver = this._maneuvers?.find(p => p.id === this._combatManeuverId)
const at = Number(context.targetNumber) const mod = Number(this.element.querySelector('[name="mod"]').value)
const malus = Number(this.element.querySelector('[name="malus"]').value) const penalty = (maneuver?.penalty ?? 0) + (maneuver?.mod?.(mod) ?? 0) ?? 0
const mod = Number(this.element.querySelector('[name="mod"]').value) const circumstance = Number(this.element.querySelector('[name="circumstance"]').value)
const maneuver = this._maneuvers?.find(p => p.id === this._combatManeuverId) this.element.querySelector('[name="penalty"]').value = penalty + circumstance
const result = at + (maneuver.mod?.(mod) ?? 0) + malus const result = (at + circumstance + penalty) ?? false
if (result) {
target.textContent = `(${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)
})) }))
} }

View File

@ -58,7 +58,14 @@ export class ActionManager {
cost: ActionManager.FREE, cost: ActionManager.FREE,
type: ActionManager.INTERACTION, type: ActionManager.INTERACTION,
source: ActionManager.SF, 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, type: ActionManager.ATTACK,
cost: ActionManager.CONTINUING, cost: ActionManager.CONTINUING,
source: ActionManager.SF, 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 mod: (value) => -value
}, },
{ {
@ -105,7 +119,14 @@ export class ActionManager {
type: ActionManager.INTERACTION, type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING, cost: ActionManager.CONTINUING,
source: ActionManager.SF, 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", name: "Abwehraktion",
@ -134,11 +155,14 @@ export class ActionManager {
cost: ActionManager.REGULAR, cost: ActionManager.REGULAR,
source: ActionManager.SF, source: ActionManager.SF,
mod: (value) => value, mod: (value) => value,
eval: (options) => eval: (options) => {
this.#hatWaffeinHand() && const step1 = this.#hatWaffeinHand() && this.#hatSonderfertigkeit("Finte", options)
this.#hatSonderfertigkeit("Finte", options) && const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Finte", options)
this.#evalSonderfertigkeitRequirements("Finte", options) if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
}
}, },
{ {
name: "Wuchtschlag", name: "Wuchtschlag",
@ -154,16 +178,28 @@ export class ActionManager {
cost: ActionManager.REGULAR, cost: ActionManager.REGULAR,
source: ActionManager.SF, source: ActionManager.SF,
mod: (value) => -(value), mod: (value) => -(value),
eval: (options) => !this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Wuchtschlag", options) eval: (options) => {
&& this.#evalSonderfertigkeitRequirements("Wuchtschlag", 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", name: "Betäubungsschlag",
type: ActionManager.ATTACK, type: ActionManager.ATTACK,
cost: ActionManager.REGULAR, cost: ActionManager.REGULAR,
source: ActionManager.SF, source: ActionManager.SF,
eval: (options) => !this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Betäubungsschlag", options) eval: (options) => {
&& this.#evalSonderfertigkeitRequirements("Betäubungsschlag", 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, type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING, cost: ActionManager.CONTINUING,
source: ActionManager.SF, source: ActionManager.SF,
eval: (options) => this.#hatMunition() eval: (options) => {
const step1 = this.#hatMunition()
&& this.#hatFernkampfWaffeinHand("Bogen", options) && this.#hatFernkampfWaffeinHand("Bogen", options)
&& this.#hatSonderfertigkeit("Schnellladen (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)", name: "Schnellladen (Armbrust)",
type: ActionManager.INTERACTION, type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING, cost: ActionManager.CONTINUING,
source: ActionManager.SF, source: ActionManager.SF,
eval: (options) => this.#hatMunition() eval: (options) => {
&& this.#hatFernkampfWaffeinHand("Armbrust", options) const step1 = this.#hatMunition()
&& this.#hatSonderfertigkeit("Schnellladen (Armbrust)", options) && this.#hatFernkampfWaffeinHand("Armbrust", options)
&& this.#evalSonderfertigkeitRequirements("Schnellladen (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", name: "Nachladen",
@ -272,7 +320,7 @@ export class ActionManager {
#evalSonderfertigkeitRequirements(nameOfSF, options) { #evalSonderfertigkeitRequirements(nameOfSF, options) {
const sf = this.actor.itemTypes["SpecialAbility"].find(p => p.name === nameOfSF) 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) { evaluate(options) {
let actionArray = [...this.#freeActions, ...this.#regularActions, ...this.#continuingActions] 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 { return {
...action, ...action,
eval: action.eval(options) eval: action.eval(options)
} }
})) })
const validActions = actionArray.filter(action => action.eval())
return validActions
} }
} }

View File

@ -17,6 +17,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
gap: 16px 0;
fieldset { fieldset {
@ -33,6 +34,10 @@
padding: 0 16px; padding: 0 16px;
} }
&.modding {
flex: 0;
}
} }
ul { ul {
@ -41,6 +46,10 @@
padding: 0; padding: 0;
margin: 0; margin: 0;
text-indent: 0; text-indent: 0;
overflow: hidden;
overflow-y: auto;
margin: 0 -8px;
max-height: 120px;
li { li {
@ -49,7 +58,7 @@
line-height: 32px; line-height: 32px;
vertical-align: middle; vertical-align: middle;
grid-template-columns: 32px 1fr 83px; grid-template-columns: 32px 1fr 90px;
grid-template-rows: 1fr; grid-template-rows: 1fr;
border: 1px transparent; border: 1px transparent;
margin: 8px; margin: 8px;
@ -69,9 +78,16 @@
.malus-and-mod { .malus-and-mod {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr; grid-template-rows: 1fr;
gap: 0 8px; gap: 0 8px;
label {
span {
text-align: center;
}
}
} }
.actions { .actions {

View File

@ -37,15 +37,18 @@
</ul> </ul>
</fieldset> </fieldset>
<fieldset> <fieldset class="modding">
<legend>Erschwernisse und Ansagen</legend> <legend>Erschwernisse und Ansagen</legend>
<div class="malus-and-mod"> <div class="malus-and-mod">
<label>Umstände <label><span>Umstände</span>
<input name="malus" type="number"> <input name="circumstance" type="number">
</label> </label>
<label>Ansage <label><span>Ansage</span>
<input name="mod" type="number" {{disabled (not canMod)}}> <input name="mod" type="number" {{disabled (not canMod)}}>
</label> </label>
<label><span>Erschwernis</span>
<input name="penalty" type="number" {{disabled true}}>
</label>
</div> </div>
</fieldset> </fieldset>